msi 3: Implement the MSIMODIFY_UPDATE command in the SELECT view

James Hawkins truiken at gmail.com
Thu Jul 26 19:35:52 CDT 2007


Hi,

This fixes the Circuit Design Suite 10 installer in vista mode.  The
installer doesn't finish, but this gets it to the point where we get
when the mode is not vista.

Changelog:
* Implement the MSIMODIFY_UPDATE command in the SELECT view.

 dlls/msi/alter.c    |   12 +++++
 dlls/msi/create.c   |    3 +
 dlls/msi/delete.c   |    3 +
 dlls/msi/distinct.c |    5 +-
 dlls/msi/insert.c   |    3 +
 dlls/msi/join.c     |   30 ++++++++++++-
 dlls/msi/msipriv.h  |   10 +++-
 dlls/msi/msiquery.c |  120 ++++++++++++++++++++++++++++-----------------------
 dlls/msi/order.c    |   19 +++++++-
 dlls/msi/select.c   |   81 +++++++++++++++++++++++++++++++++-
 dlls/msi/streams.c  |   12 +++++
 dlls/msi/table.c    |   29 +++++++++---
 dlls/msi/tests/db.c |   20 ++-------
 dlls/msi/update.c   |    3 +
 dlls/msi/where.c    |   22 +++++++++
 15 files changed, 277 insertions(+), 95 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c
index cfb8ab4..587b4be 100644
--- a/dlls/msi/alter.c
+++ b/dlls/msi/alter.c
@@ -61,6 +61,15 @@ static UINT ALTER_fetch_stream( struct t
     return ERROR_FUNCTION_FAILED;
 }
 
+static UINT ALTER_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSIALTERVIEW *av = (MSIALTERVIEW*)view;
+
+    TRACE("%p %d %p\n", av, row, rec );
+
+    return av->table->ops->get_row(av->table, row, rec);
+}
+
 static UINT ITERATE_columns(MSIRECORD *row, LPVOID param)
 {
     (*(UINT *)param)++;
@@ -179,7 +188,7 @@ static UINT ALTER_get_column_info( struc
 }
 
 static UINT ALTER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                          MSIRECORD *rec, UINT row )
 {
     MSIALTERVIEW *av = (MSIALTERVIEW*)view;
 
@@ -211,6 +220,7 @@ static const MSIVIEWOPS alter_ops =
 {
     ALTER_fetch_int,
     ALTER_fetch_stream,
+    ALTER_get_row,
     NULL,
     NULL,
     NULL,
diff --git a/dlls/msi/create.c b/dlls/msi/create.c
index 8f33ec3..ed6b43a 100644
--- a/dlls/msi/create.c
+++ b/dlls/msi/create.c
@@ -96,7 +96,7 @@ static UINT CREATE_get_column_info( stru
 }
 
 static UINT CREATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec)
+                           MSIRECORD *rec, UINT row)
 {
     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
 
@@ -124,6 +124,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 7e00484..57b0a2e 100644
--- a/dlls/msi/delete.c
+++ b/dlls/msi/delete.c
@@ -147,7 +147,7 @@ static UINT DELETE_get_column_info( stru
 }
 
 static UINT DELETE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                           MSIRECORD *rec, UINT row )
 {
     MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
 
@@ -186,6 +186,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 0da3c2e..2fe5eff 100644
--- a/dlls/msi/distinct.c
+++ b/dlls/msi/distinct.c
@@ -218,7 +218,7 @@ static UINT DISTINCT_get_column_info( st
 }
 
 static UINT DISTINCT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                             MSIRECORD *rec, UINT row )
 {
     MSIDISTINCTVIEW *dv = (MSIDISTINCTVIEW*)view;
 
@@ -227,7 +227,7 @@ static UINT DISTINCT_modify( struct tagM
     if( !dv->table )
          return ERROR_FUNCTION_FAILED;
 
-    return dv->table->ops->modify( dv->table, eModifyMode, rec );
+    return dv->table->ops->modify( dv->table, eModifyMode, rec, row );
 }
 
 static UINT DISTINCT_delete( struct tagMSIVIEW *view )
@@ -275,6 +275,7 @@ static const MSIVIEWOPS distinct_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     DISTINCT_execute,
     DISTINCT_close,
     DISTINCT_get_dimensions,
diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c
index d122624..206c3d7 100644
--- a/dlls/msi/insert.c
+++ b/dlls/msi/insert.c
@@ -185,7 +185,7 @@ static UINT INSERT_get_column_info( stru
     return sv->ops->get_column_info( sv, n, name, type );
 }
 
-static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec)
+static UINT INSERT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
 {
     MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
 
@@ -226,6 +226,7 @@ static const MSIVIEWOPS insert_ops =
     NULL,
     NULL,
     NULL,
+    NULL,
     INSERT_execute,
     INSERT_close,
     INSERT_get_dimensions,
diff --git a/dlls/msi/join.c b/dlls/msi/join.c
index fa31ad3..e071078 100644
--- a/dlls/msi/join.c
+++ b/dlls/msi/join.c
@@ -104,6 +104,33 @@ static UINT JOIN_fetch_stream( struct ta
     return table->ops->fetch_stream( table, row, col, stm );
 }
 
+static UINT JOIN_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
+    MSIVIEW *table;
+
+    TRACE("%p %d %p\n", jv, row, rec );
+
+    if( !jv->left || !jv->right )
+             return ERROR_FUNCTION_FAILED;
+
+    if( row >= jv->left_rows * jv->right_rows )
+         return ERROR_FUNCTION_FAILED;
+
+    if( row <= jv->left_count )
+    {
+        table = jv->left;
+        row = (row/jv->right_rows);
+    }
+    else
+    {
+        table = jv->right;
+        row = (row % jv->right_rows);
+    }
+
+    return table->ops->get_row(table, row, rec);
+}
+
 static UINT JOIN_execute( struct tagMSIVIEW *view, MSIRECORD *record )
 {
     MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
@@ -201,7 +228,7 @@ static UINT JOIN_get_column_info( struct
 }
 
 static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                         MSIRECORD *rec, UINT row )
 {
     MSIJOINVIEW *jv = (MSIJOINVIEW*)view;
 
@@ -243,6 +270,7 @@ static const MSIVIEWOPS join_ops =
 {
     JOIN_fetch_int,
     JOIN_fetch_stream,
+    JOIN_get_row,
     NULL,
     NULL,
     NULL,
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 0036414..d4ccd80 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -157,6 +157,12 @@ typedef struct tagMSIVIEWOPS
     UINT (*fetch_stream)( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm );
 
     /*
+     * get_row - gets values from a row
+     *
+     */
+    UINT (*get_row)( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec );
+
+    /*
      * set_row - sets values in a row as specified by mask
      *
      *  Similar semantics to fetch_int
@@ -203,7 +209,7 @@ typedef struct tagMSIVIEWOPS
     /*
      * modify - not yet implemented properly
      */
-    UINT (*modify)( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record );
+    UINT (*modify)( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *record, UINT row );
 
     /*
      * delete - destroys the structure completely
@@ -690,7 +696,7 @@ extern UINT MSI_ViewClose( MSIQUERY* );
 extern UINT MSI_ViewGetColumnInfo(MSIQUERY *, MSICOLINFO, MSIRECORD **);
 extern UINT MSI_ViewModify( MSIQUERY *, MSIMODIFY, MSIRECORD * );
 extern UINT VIEW_find_column( MSIVIEW *, LPCWSTR, UINT * );
-
+extern UINT msi_view_get_row(MSIDATABASE *, MSIVIEW *, UINT, MSIRECORD **);
 
 /* install internals */
 extern UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel );
diff --git a/dlls/msi/msiquery.c b/dlls/msi/msiquery.c
index abec8d8..32bbf97 100644
--- a/dlls/msi/msiquery.c
+++ b/dlls/msi/msiquery.c
@@ -265,90 +265,102 @@ UINT WINAPI MsiDatabaseOpenViewW(MSIHAND
     return ret;
 }
 
-UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
+UINT msi_view_get_row(MSIDATABASE *db, MSIVIEW *view, UINT row, MSIRECORD **rec)
 {
-    MSIVIEW *view;
-    MSIRECORD *rec;
     UINT row_count = 0, col_count = 0, i, ival, ret, type;
 
-    TRACE("%p %p\n", query, prec );
-
-    view = query->view;
-    if( !view )
-        return ERROR_FUNCTION_FAILED;
+    TRACE("%p %p %d %p\n", db, view, row, rec);
 
-    ret = view->ops->get_dimensions( view, &row_count, &col_count );
-    if( ret )
+    ret = view->ops->get_dimensions(view, &row_count, &col_count);
+    if (ret)
         return ret;
-    if( !col_count )
+
+    if (!col_count)
         return ERROR_INVALID_PARAMETER;
 
-    if( query->row >= row_count )
+    if (row >= row_count)
         return ERROR_NO_MORE_ITEMS;
 
-    rec = MSI_CreateRecord( col_count );
-    if( !rec )
+    *rec = MSI_CreateRecord(col_count);
+    if (!*rec)
         return ERROR_FUNCTION_FAILED;
 
-    for( i=1; i<=col_count; i++ )
+    for (i = 1; i <= col_count; i++)
     {
-        ret = view->ops->get_column_info( view, i, NULL, &type );
-        if( ret )
+        ret = view->ops->get_column_info(view, i, NULL, &type);
+        if (ret)
         {
-            ERR("Error getting column type for %d\n", i );
+            ERR("Error getting column type for %d\n", i);
             continue;
         }
-        if (!MSITYPE_IS_BINARY(type))
+
+        if (MSITYPE_IS_BINARY(type))
         {
-            ret = view->ops->fetch_int( view, query->row, i, &ival );
-            if( ret )
+            IStream *stm = NULL;
+
+            ret = view->ops->fetch_stream(view, row, i, &stm);
+            if ((ret == ERROR_SUCCESS) && stm)
             {
-                ERR("Error fetching data for %d\n", i );
-                continue;
+                MSI_RecordSetIStream(*rec, i, stm);
+                IStream_Release(stm);
             }
-            if( ! (type & MSITYPE_VALID ) )
-                ERR("Invalid type!\n");
+            else
+                ERR("failed to get stream\n");
 
-            /* check if it's nul (0) - if so, don't set anything */
-            if( !ival )
-                continue;
+            continue;
+        }
 
-            if( type & MSITYPE_STRING )
-            {
-                LPCWSTR sval;
+        ret = view->ops->fetch_int(view, row, i, &ival);
+        if (ret)
+        {
+            ERR("Error fetching data for %d\n", i);
+            continue;
+        }
 
-                sval = msi_string_lookup_id( query->db->strings, ival );
-                MSI_RecordSetStringW( rec, i, sval );
-            }
-            else
-            {
-                if( (type & MSI_DATASIZEMASK) == 2 )
-                    MSI_RecordSetInteger( rec, i, ival - (1<<15) );
-                else
-                    MSI_RecordSetInteger( rec, i, ival - (1<<31) );
-            }
+        if (! (type & MSITYPE_VALID))
+            ERR("Invalid type!\n");
+
+        /* check if it's nul (0) - if so, don't set anything */
+        if (!ival)
+            continue;
+
+        if (type & MSITYPE_STRING)
+        {
+            LPCWSTR sval;
+
+            sval = msi_string_lookup_id(db->strings, ival);
+            MSI_RecordSetStringW(*rec, i, sval);
         }
         else
         {
-            IStream *stm = NULL;
-
-            ret = view->ops->fetch_stream( view, query->row, i, &stm );
-            if( ( ret == ERROR_SUCCESS ) && stm )
-            {
-                MSI_RecordSetIStream( rec, i, stm );
-                IStream_Release( stm );
-            }
+            if ((type & MSI_DATASIZEMASK) == 2)
+                MSI_RecordSetInteger(*rec, i, ival - (1<<15));
             else
-                ERR("failed to get stream\n");
+                MSI_RecordSetInteger(*rec, i, ival - (1<<31));
         }
     }
-    query->row ++;
-
-    *prec = rec;
 
     return ERROR_SUCCESS;
 }
 
+UINT MSI_ViewFetch(MSIQUERY *query, MSIRECORD **prec)
+{
+    MSIVIEW *view;
+    UINT r;
+
+    TRACE("%p %p\n", query, prec );
+
+    view = query->view;
+    if( !view )
+        return ERROR_FUNCTION_FAILED;
+
+    r = msi_view_get_row(query->db, view, query->row, prec);
+    if (r == ERROR_SUCCESS)
+        query->row ++;
+
+    return r;
+}
+
 UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
 {
     MSIQUERY *query;
@@ -563,7 +575,7 @@ UINT MSI_ViewModify( MSIQUERY *query, MS
     if ( !view  || !view->ops->modify)
         return ERROR_FUNCTION_FAILED;
 
-    return view->ops->modify( view, mode, rec );
+    return view->ops->modify( view, mode, rec, query->row );
 }
 
 UINT WINAPI MsiViewModify( MSIHANDLE hView, MSIMODIFY eModifyMode,
diff --git a/dlls/msi/order.c b/dlls/msi/order.c
index c745be5..e895d59 100644
--- a/dlls/msi/order.c
+++ b/dlls/msi/order.c
@@ -142,6 +142,20 @@ static UINT ORDER_fetch_int( struct tagM
     return ov->table->ops->fetch_int( ov->table, row, col, val );
 }
 
+static UINT ORDER_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSIORDERVIEW *ov = (MSIORDERVIEW *)view;
+
+    TRACE("%p %d %p\n", ov, row, rec );
+
+    if (!ov->table)
+        return ERROR_FUNCTION_FAILED;
+
+    row = ov->reorder[row];
+
+    return ov->table->ops->get_row(ov->table, row, rec);
+}
+
 static UINT ORDER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
 {
     MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
@@ -219,7 +233,7 @@ static UINT ORDER_get_column_info( struc
 }
 
 static UINT ORDER_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                          MSIRECORD *rec, UINT row )
 {
     MSIORDERVIEW *ov = (MSIORDERVIEW*)view;
 
@@ -228,7 +242,7 @@ static UINT ORDER_modify( struct tagMSIV
     if( !ov->table )
          return ERROR_FUNCTION_FAILED;
 
-    return ov->table->ops->modify( ov->table, eModifyMode, rec );
+    return ov->table->ops->modify( ov->table, eModifyMode, rec, row );
 }
 
 static UINT ORDER_delete( struct tagMSIVIEW *view )
@@ -272,6 +286,7 @@ static const MSIVIEWOPS order_ops =
 {
     ORDER_fetch_int,
     NULL,
+    ORDER_get_row,
     NULL,
     NULL,
     NULL,
diff --git a/dlls/msi/select.c b/dlls/msi/select.c
index 0643f50..d170b19 100644
--- a/dlls/msi/select.c
+++ b/dlls/msi/select.c
@@ -82,6 +82,18 @@ static UINT SELECT_fetch_stream( struct 
     return sv->table->ops->fetch_stream( sv->table, row, col, stm );
 }
 
+static UINT SELECT_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSISELECTVIEW *sv = (MSISELECTVIEW *)view;
+
+    TRACE("%p %d %p\n", sv, row, rec );
+
+    if( !sv->table )
+         return ERROR_FUNCTION_FAILED;
+
+    return msi_view_get_row(sv->db, view, row, rec);
+}
+
 static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
 {
     MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
@@ -214,17 +226,79 @@ static UINT SELECT_get_column_info( stru
     return sv->table->ops->get_column_info( sv->table, n, name, type );
 }
 
+static UINT msi_select_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
+{
+    MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
+    UINT r, i, num_columns, col, type, val;
+    LPWSTR name;
+    LPCWSTR str;
+    MSIRECORD *mod;
+
+    r = SELECT_get_dimensions(view, NULL, &num_columns);
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    r = sv->table->ops->get_row(sv->table, row - 1, &mod);
+    if (r != ERROR_SUCCESS)
+        return r;
+
+    for (i = 0; i < num_columns; i++)
+    {
+        col = sv->cols[i];
+
+        r = SELECT_get_column_info(view, i + 1, &name, &type);
+        msi_free(name);
+        if (r != ERROR_SUCCESS)
+        {
+            ERR("Failed to get column information: %d\n", r);
+            goto done;
+        }
+
+        if (MSITYPE_IS_BINARY(type))
+        {
+            ERR("Cannot modify binary data!\n");
+            r = ERROR_FUNCTION_FAILED;
+            goto done;
+        }
+        else if (type & MSITYPE_STRING)
+        {
+            str = MSI_RecordGetString(rec, i + 1);
+            r = MSI_RecordSetStringW(mod, col, str);
+        }
+        else
+        {
+            val = MSI_RecordGetInteger(rec, i + 1);
+            r = MSI_RecordSetInteger(mod, col, val);
+        }
+
+        if (r != ERROR_SUCCESS)
+        {
+            ERR("Failed to modify record: %d\n", r);
+            goto done;
+        }
+    }
+
+    r = sv->table->ops->modify(sv->table, MSIMODIFY_UPDATE, mod, row);
+
+done:
+    msiobj_release(&mod->hdr);
+    return r;
+}
+
 static UINT SELECT_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                           MSIRECORD *rec, UINT row )
 {
     MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
 
-    TRACE("%p %d %p\n", sv, eModifyMode, rec );
+    TRACE("%p %d %p %d\n", sv, eModifyMode, rec, row );
 
     if( !sv->table )
          return ERROR_FUNCTION_FAILED;
 
-    return sv->table->ops->modify( sv->table, eModifyMode, rec );
+    if (eModifyMode == MSIMODIFY_UPDATE)
+        return msi_select_update(view, rec, row);
+
+    return sv->table->ops->modify( sv->table, eModifyMode, rec, row );
 }
 
 static UINT SELECT_delete( struct tagMSIVIEW *view )
@@ -265,6 +339,7 @@ static const MSIVIEWOPS select_ops =
 {
     SELECT_fetch_int,
     SELECT_fetch_stream,
+    SELECT_get_row,
     SELECT_set_row,
     SELECT_insert_row,
     NULL,
diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c
index 229a34f..4a40a12 100644
--- a/dlls/msi/streams.c
+++ b/dlls/msi/streams.c
@@ -129,6 +129,15 @@ static UINT STREAMS_fetch_stream(struct 
     return ERROR_SUCCESS;
 }
 
+static UINT STREAMS_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
+
+    FIXME("%p %d %p\n", sv, row, rec);
+
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
 static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
 {
     FIXME("(%p, %d, %p, %d): stub!\n", view, row, rec, mask);
@@ -269,7 +278,7 @@ static UINT STREAMS_get_column_info(stru
     return ERROR_SUCCESS;
 }
 
-static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec)
+static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
 {
     FIXME("(%p, %d, %p): stub!\n", view, eModifyMode, rec);
     return ERROR_SUCCESS;
@@ -327,6 +336,7 @@ static const MSIVIEWOPS streams_ops =
 {
     STREAMS_fetch_int,
     STREAMS_fetch_stream,
+    STREAMS_get_row,
     STREAMS_set_row,
     STREAMS_insert_row,
     STREAMS_delete_row,
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 5333817..61c07f4 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -1277,6 +1277,17 @@ static UINT TABLE_set_int( MSITABLEVIEW 
     return ERROR_SUCCESS;
 }
 
+static UINT TABLE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
+    UINT r;
+
+    if (!tv->table)
+        return ERROR_INVALID_PARAMETER;
+
+    return msi_view_get_row(tv->db, view, row, rec);
+}
+
 static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@@ -1532,10 +1543,10 @@ static UINT TABLE_delete_row( struct tag
     return ERROR_SUCCESS;
 }
 
-static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec)
+static UINT msi_table_update(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row)
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
-    UINT r, row;
+    UINT r, new_row;
 
     /* FIXME: MsiViewFetch should set rec index 0 to some ID that
      * sets the fetched record apart from other records
@@ -1544,19 +1555,22 @@ static UINT msi_table_update(struct tagM
     if (!tv->table)
         return ERROR_INVALID_PARAMETER;
 
-    r = msi_table_find_row(tv, rec, &row);
+    r = msi_table_find_row(tv, rec, &new_row);
     if (r != ERROR_SUCCESS)
+    {
+        ERR("can't find row to modify\n");
         return ERROR_SUCCESS;
+    }
 
     /* the row cannot be changed */
-    if (row != 0)
+    if (row != new_row + 1)
         return ERROR_FUNCTION_FAILED;
 
-    return TABLE_set_row(view, row, rec, (1 << tv->num_cols) - 1);
+    return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
 }
 
 static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec)
+                          MSIRECORD *rec, UINT row)
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
     UINT r;
@@ -1577,7 +1591,7 @@ static UINT TABLE_modify( struct tagMSIV
         break;
 
     case MSIMODIFY_UPDATE:
-        r = msi_table_update( view, rec );
+        r = msi_table_update( view, rec, row );
         break;
 
     case MSIMODIFY_REFRESH:
@@ -1826,6 +1840,7 @@ static const MSIVIEWOPS table_ops =
 {
     TABLE_fetch_int,
     TABLE_fetch_stream,
+    TABLE_get_row,
     TABLE_set_row,
     TABLE_insert_row,
     TABLE_delete_row,
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c
index 0fbee89..39ef6ac 100644
--- a/dlls/msi/tests/db.c
+++ b/dlls/msi/tests/db.c
@@ -3841,10 +3841,7 @@ static void test_viewmodify_update(void)
     r = MsiRecordGetInteger(hrec, 1);
     ok(r == 1, "Expected 1, got %d\n", r);
     r = MsiRecordGetInteger(hrec, 2);
-    todo_wine
-    {
-        ok(r == 0, "Expected 0, got %d\n", r);
-    }
+    ok(r == 0, "Expected 0, got %d\n", r);
 
     r = MsiCloseHandle(hrec);
     ok(r == ERROR_SUCCESS, "failed to close record\n");
@@ -3918,10 +3915,7 @@ static void test_viewmodify_update(void)
     r = MsiRecordGetInteger(hrec, 1);
     ok(r == 1, "Expected 1, got %d\n", r);
     r = MsiRecordGetInteger(hrec, 2);
-    todo_wine
-    {
-        ok(r == 0, "Expected 0, got %d\n", r);
-    }
+    ok(r == 0, "Expected 0, got %d\n", r);
 
     r = MsiCloseHandle(hrec);
     ok(r == ERROR_SUCCESS, "failed to close record\n");
@@ -3932,10 +3926,7 @@ static void test_viewmodify_update(void)
     r = MsiRecordGetInteger(hrec, 1);
     ok(r == 3, "Expected 3, got %d\n", r);
     r = MsiRecordGetInteger(hrec, 2);
-    todo_wine
-    {
-        ok(r == 0, "Expected 0, got %d\n", r);
-    }
+    ok(r == 0, "Expected 0, got %d\n", r);
 
     r = MsiCloseHandle(hrec);
     ok(r == ERROR_SUCCESS, "failed to close record\n");
@@ -3946,10 +3937,7 @@ static void test_viewmodify_update(void)
     r = MsiRecordGetInteger(hrec, 1);
     ok(r == 5, "Expected 5, got %d\n", r);
     r = MsiRecordGetInteger(hrec, 2);
-    todo_wine
-    {
-        ok(r == 0, "Expected 0, got %d\n", r);
-    }
+    ok(r == 0, "Expected 0, got %d\n", r);
 
     r = MsiCloseHandle(hrec);
     ok(r == ERROR_SUCCESS, "failed to close record\n");
diff --git a/dlls/msi/update.c b/dlls/msi/update.c
index 10f7762..23d7ab5 100644
--- a/dlls/msi/update.c
+++ b/dlls/msi/update.c
@@ -138,7 +138,7 @@ static UINT UPDATE_get_column_info( stru
 }
 
 static UINT UPDATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                           MSIRECORD *rec, UINT row )
 {
     MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
 
@@ -178,6 +178,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 fddb0e7..c6a1181 100644
--- a/dlls/msi/where.c
+++ b/dlls/msi/where.c
@@ -82,6 +82,23 @@ static UINT WHERE_fetch_stream( struct t
     return wv->table->ops->fetch_stream( wv->table, row, col, stm );
 }
 
+static UINT WHERE_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
+{
+    MSIWHEREVIEW *wv = (MSIWHEREVIEW *)view;
+
+    TRACE("%p %d %p\n", wv, row, rec );
+
+    if (!wv->table)
+        return ERROR_FUNCTION_FAILED;
+
+    if (row > wv->row_count)
+        return ERROR_NO_MORE_ITEMS;
+
+    row = wv->reorder[row];
+
+    return wv->table->ops->get_row(view, row, rec);
+}
+
 static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
 {
     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
@@ -379,7 +396,7 @@ static UINT WHERE_get_column_info( struc
 }
 
 static UINT WHERE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
-                MSIRECORD *rec )
+                          MSIRECORD *rec, UINT row )
 {
     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
 
@@ -388,7 +405,7 @@ static UINT WHERE_modify( struct tagMSIV
     if( !wv->table )
          return ERROR_FUNCTION_FAILED;
 
-    return wv->table->ops->modify( wv->table, eModifyMode, rec );
+    return wv->table->ops->modify( wv->table, eModifyMode, rec, row );
 }
 
 static UINT WHERE_delete( struct tagMSIVIEW *view )
@@ -437,6 +454,7 @@ static const MSIVIEWOPS where_ops =
 {
     WHERE_fetch_int,
     WHERE_fetch_stream,
+    WHERE_get_row,
     WHERE_set_row,
     NULL,
     NULL,
-- 
1.4.1


More information about the wine-patches mailing list