MSI: Fetch binary streams at the table level

Mike McCormack mike at codeweavers.com
Sat Jul 3 20:33:31 CDT 2004


ChangeLog:
* Fetch binary streams at the table level
-------------- next part --------------
diff -ur dlls/msi.old/action.c dlls/msi/action.c
--- dlls/msi.old/action.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/action.c	2004-07-03 20:30:56.000000000 -0500
@@ -79,7 +79,7 @@
     BOOL FeatureState;
     BOOL Enabled;
     INT  Cost;
-}MSICOMPONENT;
+} MSICOMPONENT;
 
 typedef struct tagMSIFOLDER
 {
@@ -89,7 +89,7 @@
 
     WCHAR ResolvedTarget[MAX_PATH];
     WCHAR ResolvedSource[MAX_PATH];
-    WCHAR Property[MAX_PATH];   /* initialy set property */
+    WCHAR Property[MAX_PATH];   /* initially set property */
     INT   ParentIndex;
     INT   State;
         /* 0 = uninitialized */
@@ -821,7 +821,7 @@
     ui_actionstart(hPackage, action);
     ui_progress(hPackage,2,1,0,0);
 
-    /* pre install, setup and configureation block */
+    /* pre install, setup and configuration block */
     if (strcmpW(action,szLaunchConditions)==0)
         rc = ACTION_LaunchConditions(hPackage);
     else if (strcmpW(action,szCostInitialize)==0)
@@ -854,7 +854,7 @@
         rc = ACTION_RegisterProgIdInfo(hPackage);
 
     /*
-     Current called during itunes but unimplemented and seem important
+     Called during itunes but unimplemented and seem important
 
      ResolveSource  (sets SourceDir)
      CreateShortcuts (would be nice to have soon)
@@ -931,7 +931,7 @@
         case 1: /* DLL file stored in a Binary table stream */
             rc = HANDLE_CustomType1(hPackage,source,target,type);
             break;
-        case 2: /* Exe file stored in a Binary table strem */
+        case 2: /* EXE file stored in a Binary table strem */
             rc = HANDLE_CustomType2(hPackage,source,target,type);
             break;
         case 35: /* Directory set with formatted text. */
@@ -1431,7 +1431,7 @@
  * The native MSI does ALOT of modification to tables here. Mostly adding alot
  * of temporary columns to the Feature and Component tables. 
  *
- *    note: native msi also tracks the short filename. but i am only going to
+ *    note: native msi also tracks the short filename. but I am only going to
  *          track the long ones.  Also looking at this directory table
  *          it appears that the directory table does not get the parents
  *          resolved base on property only based on their entrys in the 
diff -ur dlls/msi.old/create.c dlls/msi/create.c
--- dlls/msi.old/create.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/create.c	2004-07-03 20:30:56.000000000 -0500
@@ -224,6 +224,7 @@
     CREATE_fetch_int,
     NULL,
     NULL,
+    NULL,
     CREATE_execute,
     CREATE_close,
     CREATE_get_dimensions,
diff -ur dlls/msi.old/distinct.c dlls/msi/distinct.c
--- dlls/msi.old/distinct.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/distinct.c	2004-07-03 20:30:56.000000000 -0500
@@ -252,6 +252,7 @@
     DISTINCT_fetch_int,
     NULL,
     NULL,
+    NULL,
     DISTINCT_execute,
     DISTINCT_close,
     DISTINCT_get_dimensions,
diff -ur dlls/msi.old/insert.c dlls/msi/insert.c
--- dlls/msi.old/insert.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/insert.c	2004-07-03 20:30:56.000000000 -0500
@@ -190,6 +190,7 @@
     INSERT_fetch_int,
     NULL,
     NULL,
+    NULL,
     INSERT_execute,
     INSERT_close,
     INSERT_get_dimensions,
diff -ur dlls/msi.old/msipriv.h dlls/msi/msipriv.h
--- dlls/msi.old/msipriv.h	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/msipriv.h	2004-07-03 20:30:56.000000000 -0500
@@ -67,6 +67,14 @@
     UINT (*fetch_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT *val );
 
     /*
+     * fetch_int - reads one integer from {row,col} in the table
+     *
+     *  This function is similar to fetch_int, except fetches a
+     *    stream instead of an integer.
+     */
+    UINT (*fetch_stream)( struct tagMSIVIEW *, UINT row, UINT col, IStream **stm );
+
+    /*
      * get_int - sets one integer at {row,col} in the table
      *
      *  Similar semantics to fetch_int
diff -ur dlls/msi.old/msiquery.c dlls/msi/msiquery.c
--- dlls/msi.old/msiquery.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/msiquery.c	2004-07-03 20:30:56.000000000 -0500
@@ -194,63 +194,49 @@
             ERR("Error getting column type for %d\n", i );
             continue;
         }
-        ret = view->ops->fetch_int( view, query->row, i, &ival );
-        if( ret )
+        if( type != MSITYPE_BINARY)
         {
-            ERR("Error fetching data for %d\n", i );
-            continue;
-        }
-        if( ! (type & MSITYPE_VALID ) )
-            ERR("Invalid type!\n");
+            ret = view->ops->fetch_int( view, query->row, i, &ival );
+            if( ret )
+            {
+                ERR("Error fetching data for %d\n", i );
+                continue;
+            }
+            if( ! (type & MSITYPE_VALID ) )
+                ERR("Invalid type!\n");
 
-        /* check if it's nul (0) - if so, don't set anything */
-        if( !ival )
-            continue;
+            /* check if it's nul (0) - if so, don't set anything */
+            if( !ival )
+                continue;
 
-        if( type & MSITYPE_STRING )
-        {
-            LPWSTR sval;
-
-            if( type != MSITYPE_BINARY)
+            if( type & MSITYPE_STRING )
             {
+                LPWSTR sval;
+
                 sval = MSI_makestring( query->db, ival );
                 MsiRecordSetStringW( handle, i, sval );
                 HeapFree( GetProcessHeap(), 0, sval );
             }
             else
             {
-                UINT refcol = 0;
-                IStream *stm = NULL;
-                WCHAR full_name[0x40];
-                static const WCHAR szBinary[] = { 'B','i','n','a','r','y','.', 0};
-                const int maxlen = (sizeof full_name - sizeof szBinary)/sizeof(WCHAR);
-
-                ret = view->ops->fetch_int( view, query->row, ival, &refcol );
-                sval = MSI_makestring( query->db, refcol );
-
-                if( sval && ( strlenW( sval ) < maxlen ) )
-                {
-                    strcpyW( full_name, szBinary );
-                    strcatW( full_name, sval );
-
-                    db_get_raw_stream( query->db, full_name, &stm );
-                    if( stm )
-                    {
-                        MSI_RecordSetIStream( handle, i, stm );
-                        IStream_Release( stm );
-                    }
-                    else
-                        ERR("failed to get stream\n");
-                    HeapFree( GetProcessHeap(), 0, sval );
-                }
+                if( (type & MSI_DATASIZEMASK) == 2 )
+                    MsiRecordSetInteger( handle, i, ival - (1<<15) );
+                else
+                    MsiRecordSetInteger( handle, i, ival - (1<<31) );
             }
         }
         else
         {
-            if( (type & MSI_DATASIZEMASK) == 2 )
-                MsiRecordSetInteger( handle, i, ival - (1<<15) );
+            IStream *stm;
+
+            ret = view->ops->fetch_stream( view, query->row, i, &stm );
+            if( ( ret == ERROR_SUCCESS ) && stm )
+            {
+                MSI_RecordSetIStream( handle, i, stm );
+                IStream_Release( stm );
+            }
             else
-                MsiRecordSetInteger( handle, i, ival - (1<<31) );
+                ERR("failed to get stream\n");
         }
     }
     query->row ++;
diff -ur dlls/msi.old/order.c dlls/msi/order.c
--- dlls/msi.old/order.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/order.c	2004-07-03 20:30:56.000000000 -0500
@@ -255,6 +255,7 @@
     ORDER_fetch_int,
     NULL,
     NULL,
+    NULL,
     ORDER_execute,
     ORDER_close,
     ORDER_get_dimensions,
diff -ur dlls/msi.old/select.c dlls/msi/select.c
--- dlls/msi.old/select.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/select.c	2004-07-03 20:30:56.000000000 -0500
@@ -65,6 +65,23 @@
     return sv->table->ops->fetch_int( sv->table, row, col, val );
 }
 
+static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
+{
+    MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
+
+    TRACE("%p %d %d %p\n", sv, row, col, stm );
+
+    if( !sv->table )
+         return ERROR_FUNCTION_FAILED;
+
+    if( (col==0) || (col>sv->num_cols) )
+         return ERROR_FUNCTION_FAILED;
+
+    col = sv->cols[ col - 1 ];
+
+    return sv->table->ops->fetch_stream( sv->table, row, col, stm );
+}
+
 static UINT SELECT_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val )
 {
     MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
@@ -181,6 +198,7 @@
 MSIVIEWOPS select_ops =
 {
     SELECT_fetch_int,
+    SELECT_fetch_stream,
     SELECT_set_int,
     SELECT_insert_row,
     SELECT_execute,
diff -ur dlls/msi.old/table.c dlls/msi/table.c
--- dlls/msi.old/table.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/table.c	2004-07-03 20:30:56.000000000 -0500
@@ -34,6 +34,8 @@
 #include "msipriv.h"
 #include "winnls.h"
 
+#include "wine/unicode.h"
+
 #include "query.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
@@ -1090,6 +1092,64 @@
     return ERROR_SUCCESS;
 }
 
+/*
+ * We need a special case for streams, as we need to reference column with
+ * the name of the stream in the same table, and the table name
+ * which may not be available at higher levels of the query
+ */
+static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm )
+{
+    MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
+    UINT ival = 0, refcol = 0, r;
+    LPWSTR sval;
+
+    if( !view->ops->fetch_int )
+        return ERROR_INVALID_PARAMETER;
+
+    /*
+     * The column marked with the type stream data seems to have a single number
+     * which references the column containing the name of the stream data
+     *
+     * Fetch the column to reference first.
+     */
+    r = view->ops->fetch_int( view, row, col, &ival );
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    /* now get the column with the name of the stream */
+    r = view->ops->fetch_int( view, row, ival, &refcol );
+    if( r != ERROR_SUCCESS )
+        return r;
+
+    /* lookup the string value from the string table */
+    sval = MSI_makestring( tv->db, refcol );
+    if( !sval )
+        return ERROR_INVALID_PARAMETER;
+
+    if( ( strlenW( sval ) + strlenW( tv->name ) + 1 ) > MAX_STREAM_NAME )
+    {
+        ERR("Name of stream is too long %s.%s\n", 
+            debugstr_w( tv->name ), debugstr_w( sval ) );
+        r = ERROR_INVALID_PARAMETER;
+    }
+    else
+    {
+        WCHAR full_name[0x40];
+        static const WCHAR szDot[] = { '.', 0 };
+
+        strcpyW( full_name, tv->name );
+        strcatW( full_name, szDot );
+        strcatW( full_name, sval );
+
+        r = db_get_raw_stream( tv->db, full_name, stm );
+        if( r )
+            ERR("fetching stream %s, error = %d\n",debugstr_w(full_name), r);
+    }
+    HeapFree( GetProcessHeap(), 0, sval );
+
+    return r;
+}
+
 static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val )
 {
     MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@@ -1268,6 +1328,7 @@
 MSIVIEWOPS table_ops =
 {
     TABLE_fetch_int,
+    TABLE_fetch_stream,
     TABLE_set_int,
     TABLE_insert_row,
     TABLE_execute,
diff -ur dlls/msi.old/update.c dlls/msi/update.c
--- dlls/msi.old/update.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/update.c	2004-07-03 20:30:56.000000000 -0500
@@ -182,6 +182,7 @@
     UPDATE_fetch_int,
     NULL,
     NULL,
+    NULL,
     UPDATE_execute,
     UPDATE_close,
     UPDATE_get_dimensions,
diff -ur dlls/msi.old/where.c dlls/msi/where.c
--- dlls/msi.old/where.c	2004-07-03 20:30:43.000000000 -0500
+++ dlls/msi/where.c	2004-07-03 20:30:56.000000000 -0500
@@ -66,6 +66,23 @@
     return wv->table->ops->fetch_int( wv->table, row, col, val );
 }
 
+static UINT WHERE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm )
+{
+    MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
+
+    TRACE("%p %d %d %p\n", wv, row, col, stm );
+
+    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->fetch_stream( wv->table, row, col, stm );
+}
+
 static UINT WHERE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val )
 {
     MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
@@ -328,6 +345,7 @@
 MSIVIEWOPS where_ops =
 {
     WHERE_fetch_int,
+    WHERE_fetch_stream,
     WHERE_set_int,
     NULL,
     WHERE_execute,


More information about the wine-patches mailing list