From ef522c5ef0aeb2563885ad0a70ffe3fa3f1489f5 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 16 Dec 2009 11:11:19 +0100 Subject: [PATCH] msi: Clone the open stream instead of trying to open a stream again. --- dlls/msi/database.c | 1 + dlls/msi/msipriv.h | 1 + dlls/msi/table.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/dlls/msi/database.c b/dlls/msi/database.c index 6ce516a78db..b485b2115e5 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -198,6 +198,7 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb) db->deletefile = strdupW( szDBPath ); list_init( &db->tables ); list_init( &db->transforms ); + list_init( &db->streams ); db->strings = msi_load_string_table( stg, &db->bytes_per_strref ); if( !db->strings ) diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 0e1a23bfaea..2f8a38c9312 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -80,6 +80,7 @@ typedef struct tagMSIDATABASE LPCWSTR mode; struct list tables; struct list transforms; + struct list streams; } MSIDATABASE; typedef struct tagMSIVIEW MSIVIEW; diff --git a/dlls/msi/table.c b/dlls/msi/table.c index fc36079f506..392fcc8a03a 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -88,6 +88,11 @@ typedef struct tagMSITRANSFORM { IStorage *stg; } MSITRANSFORM; +typedef struct tagMSISTREAM { + struct list entry; + IStream *stm; +} MSISTREAM; + static const WCHAR szStringData[] = { '_','S','t','r','i','n','g','D','a','t','a',0 }; static const WCHAR szStringPool[] = { @@ -332,6 +337,66 @@ end: return ret; } +static UINT find_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm ) +{ + MSISTREAM *stream; + + LIST_FOR_EACH_ENTRY( stream, &db->streams, MSISTREAM, entry ) + { + HRESULT r; + STATSTG stat; + + r = IStream_Stat( stream->stm, &stat, 0 ); + if( FAILED( r ) ) + { + WARN("failed to stat stream r = %08x!\n", r); + continue; + } + + if( !lstrcmpW( name, stat.pwcsName ) ) + { + TRACE("found %s\n", debugstr_w(name)); + *stm = stream->stm; + CoTaskMemFree( stat.pwcsName ); + return ERROR_SUCCESS; + } + + CoTaskMemFree( stat.pwcsName ); + } + + return ERROR_FUNCTION_FAILED; +} + +static UINT clone_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm ) +{ + IStream *stream; + + if (find_open_stream( db, name, &stream ) == ERROR_SUCCESS) + { + HRESULT r; + LARGE_INTEGER pos; + + r = IStream_Clone( stream, stm ); + if( FAILED( r ) ) + { + WARN("failed to clone stream r = %08x!\n", r); + return ERROR_FUNCTION_FAILED; + } + + pos.QuadPart = 0; + r = IStream_Seek( *stm, pos, STREAM_SEEK_SET, NULL ); + if( FAILED( r ) ) + { + IStream_Release( *stm ); + return ERROR_FUNCTION_FAILED; + } + + return ERROR_SUCCESS; + } + + return ERROR_FUNCTION_FAILED; +} + static UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) { LPWSTR encname; @@ -341,6 +406,12 @@ static UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) TRACE("%s -> %s\n",debugstr_w(stname),debugstr_w(encname)); + if (clone_open_stream( db, encname, stm ) == ERROR_SUCCESS) + { + msi_free( encname ); + return ERROR_SUCCESS; + } + r = IStorage_OpenStream(db->storage, encname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm); if( FAILED( r ) ) @@ -359,7 +430,20 @@ static UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) msi_free( encname ); - return SUCCEEDED(r) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED; + if( SUCCEEDED(r) ) + { + MSISTREAM *stream; + + stream = msi_alloc( sizeof(MSISTREAM) ); + if( !stream ) + return ERROR_NOT_ENOUGH_MEMORY; + + stream->stm = *stm; + IStream_AddRef( *stm ); + list_add_tail( &db->streams, &stream->entry ); + } + + return ERROR_SUCCESS; } UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname, @@ -3041,3 +3125,15 @@ void msi_free_transforms( MSIDATABASE *db ) msi_free( t ); } } + +void msi_free_streams( MSIDATABASE *db ) +{ + while( !list_empty( &db->streams ) ) + { + MSISTREAM *s = LIST_ENTRY( list_head( &db->streams ), + MSISTREAM, entry ); + list_remove( &s->entry ); + IStream_Release( s->stm ); + msi_free( s ); + } +} -- 2.11.4.GIT