msi 3: Implement the MSIMODIFY_UPDATE command in the SELECT view

James Hawkins truiken at gmail.com
Thu Jul 26 19:40:38 CDT 2007


On 7/26/07, James Hawkins <truiken at gmail.com> wrote:
> 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(-)
>

Please use this version instead; I accidentally left an unused
variable in the last patch.

-- 
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,16 @@ 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;
+
+    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 +1554,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 +1839,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