https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9cf1ecf2f3813427b4483…
commit 9cf1ecf2f3813427b4483d2498b6d04b51aa5c34
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Sun Mar 13 19:08:42 2022 +0100
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Mar 20 19:28:31 2022 +0100
[WINESYNC] msi: Fix adding temporary columns.
Signed-off-by: Piotr Caban <piotr(a)codeweavers.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
wine commit id 15b47513a1926a103492e0774396119f57d2e8d5 by Piotr Caban
<piotr(a)codeweavers.com>
---
dll/win32/msi/alter.c | 82 +---------------------------
dll/win32/msi/msipriv.h | 2 +-
dll/win32/msi/table.c | 105 ++++++++++++++++++++++++++++--------
modules/rostests/winetests/msi/db.c | 10 +++-
4 files changed, 95 insertions(+), 104 deletions(-)
diff --git a/dll/win32/msi/alter.c b/dll/win32/msi/alter.c
index 7922171ae25..78f1a3930c7 100644
--- a/dll/win32/msi/alter.c
+++ b/dll/win32/msi/alter.c
@@ -61,85 +61,6 @@ static UINT ALTER_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT
col, ISt
return ERROR_FUNCTION_FAILED;
}
-static UINT ITERATE_columns(MSIRECORD *row, LPVOID param)
-{
- (*(UINT *)param)++;
- return ERROR_SUCCESS;
-}
-
-static BOOL check_column_exists(MSIDATABASE *db, LPCWSTR table, LPCWSTR column)
-{
- MSIQUERY *view;
- MSIRECORD *rec;
- UINT r;
-
- static const WCHAR query[] = {
- 'S','E','L','E','C','T','
','*',' ','F','R','O','M','
',
-
'`','_','C','o','l','u','m','n','s','`','
','W','H','E','R','E',' ',
-
'`','T','a','b','l','e','`','=','\'','%','s','\'','
','A','N','D',' ',
-
'`','N','a','m','e','`','=','\'','%','s','\'',0
- };
-
- r = MSI_OpenQuery(db, &view, query, table, column);
- if (r != ERROR_SUCCESS)
- return FALSE;
-
- r = MSI_ViewExecute(view, NULL);
- if (r != ERROR_SUCCESS)
- goto done;
-
- r = MSI_ViewFetch(view, &rec);
- if (r == ERROR_SUCCESS)
- msiobj_release(&rec->hdr);
-
-done:
- msiobj_release(&view->hdr);
- return (r == ERROR_SUCCESS);
-}
-
-static UINT alter_add_column(MSIALTERVIEW *av)
-{
- UINT r, colnum = 1;
- MSIQUERY *view;
- MSIVIEW *columns;
-
- static const WCHAR szColumns[] =
{'_','C','o','l','u','m','n','s',0};
- static const WCHAR query[] = {
- 'S','E','L','E','C','T','
','*',' ','F','R','O','M','
',
-
'`','_','C','o','l','u','m','n','s','`','
','W','H','E','R','E',' ',
-
'`','T','a','b','l','e','`','=','\'','%','s','\'','
','O','R','D','E','R',' ',
- 'B','Y','
','`','N','u','m','b','e','r','`',0
- };
-
- r = TABLE_CreateView(av->db, szColumns, &columns);
- if (r != ERROR_SUCCESS)
- return r;
-
- if (check_column_exists(av->db, av->colinfo->table,
av->colinfo->column))
- {
- columns->ops->delete(columns);
- return ERROR_BAD_QUERY_SYNTAX;
- }
-
- r = MSI_OpenQuery(av->db, &view, query, av->colinfo->table,
av->colinfo->column);
- if (r == ERROR_SUCCESS)
- {
- r = MSI_IterateRecords(view, NULL, ITERATE_columns, &colnum);
- msiobj_release(&view->hdr);
- if (r != ERROR_SUCCESS)
- {
- columns->ops->delete(columns);
- return r;
- }
- }
- r = columns->ops->add_column(columns, av->colinfo->table,
- colnum, av->colinfo->column,
- av->colinfo->type, (av->hold == 1));
-
- columns->ops->delete(columns);
- return r;
-}
-
static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{
MSIALTERVIEW *av = (MSIALTERVIEW*)view;
@@ -148,7 +69,8 @@ static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record
)
TRACE("%p %p\n", av, record);
if (av->colinfo)
- return alter_add_column(av);
+ return av->table->ops->add_column(av->table,
av->colinfo->column,
+ av->colinfo->type, av->colinfo->temporary, av->hold ==
1);
if (av->hold == 1)
av->table->ops->add_ref(av->table);
diff --git a/dll/win32/msi/msipriv.h b/dll/win32/msi/msipriv.h
index 6f2992d10ea..97126e39693 100644
--- a/dll/win32/msi/msipriv.h
+++ b/dll/win32/msi/msipriv.h
@@ -337,7 +337,7 @@ typedef struct tagMSIVIEWOPS
/*
* add_column - adds a column to the table
*/
- UINT (*add_column)( struct tagMSIVIEW *view, LPCWSTR table, UINT number, LPCWSTR
column, UINT type, BOOL hold );
+ UINT (*add_column)( struct tagMSIVIEW *view, LPCWSTR column, INT type, BOOL
temporary, BOOL hold );
/*
* sort - orders the table by columns
diff --git a/dll/win32/msi/table.c b/dll/win32/msi/table.c
index c6171106043..5a1466592f1 100644
--- a/dll/win32/msi/table.c
+++ b/dll/win32/msi/table.c
@@ -2040,38 +2040,99 @@ static UINT TABLE_release(struct tagMSIVIEW *view)
return ref;
}
-static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number,
- LPCWSTR column, UINT type, BOOL hold)
+static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR column,
+ INT type, BOOL temporary, BOOL hold)
{
+ UINT i, r, table_id, col_id, size, offset;
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
- MSITABLE *msitable;
- MSIRECORD *rec;
- UINT r;
+ MSICOLUMNINFO *colinfo;
- rec = MSI_CreateRecord(4);
- if (!rec)
- return ERROR_OUTOFMEMORY;
+ if (temporary && !hold && !tv->table->ref_count)
+ return ERROR_SUCCESS;
- MSI_RecordSetStringW(rec, 1, table);
- MSI_RecordSetInteger(rec, 2, number);
- MSI_RecordSetStringW(rec, 3, column);
- MSI_RecordSetInteger(rec, 4, type);
+ if (!temporary && tv->table->col_count &&
+ tv->table->colinfo[tv->table->col_count-1].temporary)
+ return ERROR_BAD_QUERY_SYNTAX;
+
+ for (i = 0; i < tv->table->col_count; i++)
+ {
+ if (!wcscmp(tv->table->colinfo[i].colname, column))
+ return ERROR_BAD_QUERY_SYNTAX;
+ }
- r = TABLE_insert_row(&tv->view, rec, -1, FALSE);
+ colinfo = msi_realloc(tv->table->colinfo, sizeof(*tv->table->colinfo) *
(tv->table->col_count + 1));
+ if (!colinfo)
+ return ERROR_OUTOFMEMORY;
+ tv->table->colinfo = colinfo;
+
+ r = msi_string2id( tv->db->strings, tv->name, -1, &table_id );
if (r != ERROR_SUCCESS)
- goto done;
+ return r;
+ col_id = msi_add_string( tv->db->strings, column, -1, !temporary );
- msi_update_table_columns(tv->db, table);
+ colinfo[tv->table->col_count].tablename = msi_string_lookup(
tv->db->strings, table_id, NULL );
+ colinfo[tv->table->col_count].number = tv->table->col_count + 1;
+ colinfo[tv->table->col_count].colname = msi_string_lookup(
tv->db->strings, col_id, NULL );
+ colinfo[tv->table->col_count].type = type;
+ colinfo[tv->table->col_count].offset = 0;
+ colinfo[tv->table->col_count].hash_table = NULL;
+ colinfo[tv->table->col_count].temporary = temporary;
+ tv->table->col_count++;
- if (!hold)
- goto done;
+ table_calc_column_offsets( tv->db, tv->table->colinfo,
tv->table->col_count);
- msitable = find_cached_table(tv->db, table);
- InterlockedIncrement(&msitable->ref_count);
+ size = msi_table_get_row_size( tv->db, tv->table->colinfo,
tv->table->col_count, LONG_STR_BYTES );
+ offset = tv->table->colinfo[tv->table->col_count - 1].offset;
+ for (i = 0; i < tv->table->row_count; i++)
+ {
+ BYTE *data = msi_realloc( tv->table->data[i], size );
+ if (!data)
+ {
+ tv->table->col_count--;
+ return ERROR_OUTOFMEMORY;
+ }
-done:
- msiobj_release(&rec->hdr);
- return r;
+ tv->table->data[i] = data;
+ memset(data + offset, 0, size - offset);
+ }
+
+ if (!temporary)
+ {
+ MSIVIEW *columns;
+ MSIRECORD *rec;
+
+ rec = MSI_CreateRecord(4);
+ if (!rec)
+ {
+ tv->table->col_count--;
+ return ERROR_OUTOFMEMORY;
+ }
+
+ MSI_RecordSetStringW(rec, 1, tv->name);
+ MSI_RecordSetInteger(rec, 2, tv->table->col_count);
+ MSI_RecordSetStringW(rec, 3, column);
+ MSI_RecordSetInteger(rec, 4, type);
+
+ r = TABLE_CreateView(tv->db, szColumns, &columns);
+ if (r != ERROR_SUCCESS)
+ {
+ tv->table->col_count--;
+ msiobj_release(&rec->hdr);
+ return r;
+ }
+
+ r = TABLE_insert_row(columns, rec, -1, FALSE);
+ columns->ops->delete(columns);
+ msiobj_release(&rec->hdr);
+ if (r != ERROR_SUCCESS)
+ {
+ tv->table->col_count--;
+ return r;
+ }
+ }
+ if (hold)
+ TABLE_add_ref(view);
+ return ERROR_SUCCESS;
}
static UINT TABLE_drop(struct tagMSIVIEW *view)
diff --git a/modules/rostests/winetests/msi/db.c b/modules/rostests/winetests/msi/db.c
index 22466548b1f..3e1c551d38f 100644
--- a/modules/rostests/winetests/msi/db.c
+++ b/modules/rostests/winetests/msi/db.c
@@ -3950,7 +3950,7 @@ static void test_temporary_table(void)
static void test_alter(void)
{
MSICONDITION cond;
- MSIHANDLE hdb = 0;
+ MSIHANDLE hdb = 0, rec;
const char *query;
UINT r;
@@ -4020,6 +4020,10 @@ static void test_alter(void)
r = run_query(hdb, 0, query);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+ query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` =
'C'";
+ r = do_query(hdb, query, &rec);
+ ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
/* add column C again */
query = "ALTER TABLE `U` ADD `C` INTEGER";
r = run_query(hdb, 0, query);
@@ -4037,6 +4041,10 @@ static void test_alter(void)
r = run_query(hdb, 0, query);
ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got
%d\n", r);
+ query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` =
'D'";
+ r = do_query(hdb, query, &rec);
+ ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
+
query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
r = run_query(hdb, 0, query);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);