[PATCH 1/5] msi: Support setting streams in msi_select_update().

Zebediah Figura z.figura12 at gmail.com
Mon Jan 28 22:11:08 CST 2019


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/msi/alter.c    |  1 +
 dlls/msi/create.c   |  1 +
 dlls/msi/delete.c   |  1 +
 dlls/msi/distinct.c |  1 +
 dlls/msi/drop.c     |  1 +
 dlls/msi/insert.c   |  1 +
 dlls/msi/msipriv.h  |  7 +++++++
 dlls/msi/select.c   |  7 +++++--
 dlls/msi/storages.c | 41 +++++++++++++++++++++++++++++++++++++++++
 dlls/msi/streams.c  | 14 ++++++++++++++
 dlls/msi/table.c    | 17 +++++++++++++++++
 dlls/msi/update.c   |  1 +
 dlls/msi/where.c    | 21 +++++++++++++++++++++
 13 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c
index d1a481ebfc..5c5893c824 100644
--- a/dlls/msi/alter.c
+++ b/dlls/msi/alter.c
@@ -221,6 +221,7 @@ static const MSIVIEWOPS alter_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     ALTER_execute,
     ALTER_close,
     ALTER_get_dimensions,
diff --git a/dlls/msi/create.c b/dlls/msi/create.c
index 3c00b70c53..2777954aa7 100644
--- a/dlls/msi/create.c
+++ b/dlls/msi/create.c
@@ -131,6 +131,7 @@ static const MSIVIEWOPS create_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     CREATE_execute,
     CREATE_close,
     CREATE_get_dimensions,
diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c
index e2e0e34678..81bd9d7db2 100644
--- a/dlls/msi/delete.c
+++ b/dlls/msi/delete.c
@@ -173,6 +173,7 @@ static const MSIVIEWOPS delete_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     DELETE_execute,
     DELETE_close,
     DELETE_get_dimensions,
diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c
index 5bd5bf8676..e102adb3de 100644
--- a/dlls/msi/distinct.c
+++ b/dlls/msi/distinct.c
@@ -256,6 +256,7 @@ static const MSIVIEWOPS distinct_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     DISTINCT_execute,
     DISTINCT_close,
     DISTINCT_get_dimensions,
diff --git a/dlls/msi/drop.c b/dlls/msi/drop.c
index 60a9202106..89fac9dfc7 100644
--- a/dlls/msi/drop.c
+++ b/dlls/msi/drop.c
@@ -101,6 +101,7 @@ static const MSIVIEWOPS drop_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     DROP_execute,
     DROP_close,
     DROP_get_dimensions,
diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c
index ed913c034c..f1185eebae 100644
--- a/dlls/msi/insert.c
+++ b/dlls/msi/insert.c
@@ -327,6 +327,7 @@ static const MSIVIEWOPS insert_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     INSERT_execute,
     INSERT_close,
     INSERT_get_dimensions,
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 3ff5ac2350..e4d2a625f7 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -256,6 +256,13 @@ typedef struct tagMSIVIEWOPS
      */
     UINT (*set_string)( struct tagMSIVIEW *view, UINT row, UINT col, const WCHAR *val, int len );
 
+    /*
+     * set_stream - set the stream value at {row, col}
+     * This function has undefined behaviour if the column does not contain
+     * streams.
+     */
+    UINT (*set_stream)( struct tagMSIVIEW *view, UINT row, UINT col, IStream *stream );
+
     /*
      * set_row - sets values in a row as specified by mask
      *
diff --git a/dlls/msi/select.c b/dlls/msi/select.c
index c6e7b20903..9d3d887f56 100644
--- a/dlls/msi/select.c
+++ b/dlls/msi/select.c
@@ -234,6 +234,7 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
 {
     MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
     UINT r, i, col, type, val;
+    IStream *stream;
     LPCWSTR str;
 
     for (i = 0; i < sv->num_cols; i++)
@@ -249,8 +250,9 @@ static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
 
         if (MSITYPE_IS_BINARY(type))
         {
-            ERR("Cannot modify binary data!\n");
-            return ERROR_FUNCTION_FAILED;
+            if (MSI_RecordGetIStream(rec, i + 1, &stream))
+                return ERROR_FUNCTION_FAILED;
+            r = sv->table->ops->set_stream(sv->table, row, col, stream);
         }
         else if (type & MSITYPE_STRING)
         {
@@ -311,6 +313,7 @@ static const MSIVIEWOPS select_ops =
     SELECT_fetch_stream,
     NULL,
     NULL,
+    NULL,
     SELECT_set_row,
     SELECT_insert_row,
     NULL,
diff --git a/dlls/msi/storages.c b/dlls/msi/storages.c
index 76a0e2e03f..521b6e89e8 100644
--- a/dlls/msi/storages.c
+++ b/dlls/msi/storages.c
@@ -153,6 +153,46 @@ done:
     return hr;
 }
 
+static UINT STORAGES_set_stream( MSIVIEW *view, UINT row, UINT col, IStream *stream )
+{
+    MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
+    IStorage *stg, *substg, *prev;
+    const WCHAR *name;
+    HRESULT hr;
+    UINT r;
+
+    TRACE("view %p, row %u, col %u, stream %p.\n", view, row, col, stream);
+
+    if ((r = stream_to_storage(stream, &stg)))
+        return r;
+
+    name = msi_string_lookup(sv->db->strings, sv->storages[row].str_index, NULL);
+
+    hr = IStorage_CreateStorage(sv->db->storage, name,
+                                STGM_WRITE | STGM_SHARE_EXCLUSIVE,
+                                0, 0, &substg);
+    if (FAILED(hr))
+    {
+        IStorage_Release(stg);
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    hr = IStorage_CopyTo(stg, 0, NULL, NULL, substg);
+    if (FAILED(hr))
+    {
+        IStorage_Release(substg);
+        IStorage_Release(stg);
+        return ERROR_FUNCTION_FAILED;
+    }
+    IStorage_Release(substg);
+
+    prev = sv->storages[row].storage;
+    sv->storages[row].storage = stg;
+    if (prev) IStorage_Release(prev);
+
+    return ERROR_SUCCESS;
+}
+
 static UINT STORAGES_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
 {
     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
@@ -404,6 +444,7 @@ static const MSIVIEWOPS storages_ops =
     STORAGES_fetch_stream,
     NULL,
     STORAGES_set_string,
+    STORAGES_set_stream,
     STORAGES_set_row,
     STORAGES_insert_row,
     STORAGES_delete_row,
diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c
index 2d458adb68..bc02fb2bac 100644
--- a/dlls/msi/streams.c
+++ b/dlls/msi/streams.c
@@ -110,6 +110,19 @@ static UINT STREAMS_set_string( struct tagMSIVIEW *view, UINT row, UINT col, con
     return ERROR_FUNCTION_FAILED;
 }
 
+static UINT STREAMS_set_stream( MSIVIEW *view, UINT row, UINT col, IStream *stream )
+{
+    MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
+    IStream *prev;
+
+    TRACE("view %p, row %u, col %u, stream %p.\n", view, row, col, stream);
+
+    prev = sv->db->streams[row].stream;
+    IStream_AddRef(sv->db->streams[row].stream = stream);
+    if (prev) IStream_Release(prev);
+    return ERROR_SUCCESS;
+}
+
 static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
 {
     MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
@@ -340,6 +353,7 @@ static const MSIVIEWOPS streams_ops =
     STREAMS_fetch_stream,
     NULL,
     STREAMS_set_string,
+    STREAMS_set_stream,
     STREAMS_set_row,
     STREAMS_insert_row,
     STREAMS_delete_row,
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index f26ab9f5b4..a2b83e27de 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -1357,6 +1357,22 @@ done:
     return r;
 }
 
+static UINT TABLE_set_stream( MSIVIEW *view, UINT row, UINT col, IStream *stream )
+{
+    MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
+    WCHAR *name;
+    UINT r;
+
+    TRACE("row %u, col %u, stream %p.\n", row, col, stream);
+
+    if ((r = get_stream_name( tv, row - 1, &name )))
+        return r;
+
+    r = add_stream( tv->db, name, stream );
+    msi_free( name );
+    return r;
+}
+
 static UINT get_table_value_from_record( MSITABLEVIEW *tv, MSIRECORD *rec, UINT iField, UINT *pvalue )
 {
     MSICOLUMNINFO columninfo;
@@ -2126,6 +2142,7 @@ static const MSIVIEWOPS table_ops =
     TABLE_fetch_stream,
     TABLE_set_int,
     TABLE_set_string,
+    TABLE_set_stream,
     TABLE_set_row,
     TABLE_insert_row,
     TABLE_delete_row,
diff --git a/dlls/msi/update.c b/dlls/msi/update.c
index af629d2236..e61342d11e 100644
--- a/dlls/msi/update.c
+++ b/dlls/msi/update.c
@@ -204,6 +204,7 @@ static const MSIVIEWOPS update_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     UPDATE_execute,
     UPDATE_close,
     UPDATE_get_dimensions,
diff --git a/dlls/msi/where.c b/dlls/msi/where.c
index eaadac4310..66de85bec9 100644
--- a/dlls/msi/where.c
+++ b/dlls/msi/where.c
@@ -299,6 +299,26 @@ static UINT WHERE_set_string(struct tagMSIVIEW *view, UINT row, UINT col, const
     return table->view->ops->set_string(table->view, rows[table->table_index], col, val, len);
 }
 
+static UINT WHERE_set_stream(MSIVIEW *view, UINT row, UINT col, IStream *stream)
+{
+    MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
+    JOINTABLE *table;
+    UINT *rows;
+    UINT r;
+
+    TRACE("view %p, row %u, col %u, stream %p.\n", wv, row, col, stream);
+
+    r = find_row(wv, row, &rows);
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    table = find_table(wv, col, &col);
+    if (!table)
+        return ERROR_FUNCTION_FAILED;
+
+    return table->view->ops->set_stream(table->view, rows[table->table_index], col, stream);
+}
+
 static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
 {
     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
@@ -1098,6 +1118,7 @@ static const MSIVIEWOPS where_ops =
     WHERE_fetch_stream,
     WHERE_set_int,
     WHERE_set_string,
+    WHERE_set_stream,
     WHERE_set_row,
     NULL,
     WHERE_delete_row,
-- 
2.20.1




More information about the wine-devel mailing list