Commit 24e9a344 authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

Fetch binary streams at the table level.

parent d784600d
......@@ -79,7 +79,7 @@ typedef struct tagMSICOMPONENT
BOOL FeatureState;
BOOL Enabled;
INT Cost;
}MSICOMPONENT;
} MSICOMPONENT;
typedef struct tagMSIFOLDER
{
......@@ -89,7 +89,7 @@ typedef struct tagMSIFOLDER
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 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
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 @@ UINT ACTION_PerformAction(MSIHANDLE hPackage, const WCHAR *action)
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 @@ static UINT ACTION_CustomAction(MSIHANDLE hPackage,const WCHAR *action)
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 @@ static void load_feature(MSIPACKAGE* package, MSIHANDLE row)
* 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
......
......@@ -224,6 +224,7 @@ MSIVIEWOPS create_ops =
CREATE_fetch_int,
NULL,
NULL,
NULL,
CREATE_execute,
CREATE_close,
CREATE_get_dimensions,
......
......@@ -252,6 +252,7 @@ MSIVIEWOPS distinct_ops =
DISTINCT_fetch_int,
NULL,
NULL,
NULL,
DISTINCT_execute,
DISTINCT_close,
DISTINCT_get_dimensions,
......
......@@ -190,6 +190,7 @@ MSIVIEWOPS insert_ops =
INSERT_fetch_int,
NULL,
NULL,
NULL,
INSERT_execute,
INSERT_close,
INSERT_get_dimensions,
......
......@@ -67,6 +67,14 @@ typedef struct tagMSIVIEWOPS
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
......
......@@ -194,63 +194,49 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *record)
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");
/* check if it's nul (0) - if so, don't set anything */
if( !ival )
continue;
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");
if( type & MSITYPE_STRING )
{
LPWSTR sval;
/* check if it's nul (0) - if so, don't set anything */
if( !ival )
continue;
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 ++;
......
......@@ -255,6 +255,7 @@ MSIVIEWOPS order_ops =
ORDER_fetch_int,
NULL,
NULL,
NULL,
ORDER_execute,
ORDER_close,
ORDER_get_dimensions,
......
......@@ -65,6 +65,23 @@ static UINT SELECT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT
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 @@ static UINT SELECT_delete( struct tagMSIVIEW *view )
MSIVIEWOPS select_ops =
{
SELECT_fetch_int,
SELECT_fetch_stream,
SELECT_set_int,
SELECT_insert_row,
SELECT_execute,
......
......@@ -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 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
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 @@ static UINT TABLE_delete( struct tagMSIVIEW *view )
MSIVIEWOPS table_ops =
{
TABLE_fetch_int,
TABLE_fetch_stream,
TABLE_set_int,
TABLE_insert_row,
TABLE_execute,
......
......@@ -182,6 +182,7 @@ static MSIVIEWOPS update_ops =
UPDATE_fetch_int,
NULL,
NULL,
NULL,
UPDATE_execute,
UPDATE_close,
UPDATE_get_dimensions,
......
......@@ -66,6 +66,23 @@ static UINT WHERE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
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 @@ static UINT WHERE_delete( struct tagMSIVIEW *view )
MSIVIEWOPS where_ops =
{
WHERE_fetch_int,
WHERE_fetch_stream,
WHERE_set_int,
NULL,
WHERE_execute,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment