On Fri, 2019-03-08 at 07:50 -0700, Erich E. Hoover wrote:
diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index bc02fb2bac..6565b3d4c4 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -218,7 +218,28 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row) { - FIXME("(%p %d): stub!\n", view, row); + MSIDATABASE *db = ((MSISTREAMSVIEW *)view)->db; + UINT i, num_rows = db->num_streams - 1;
You should handle db->num_streams == 0.
+ const WCHAR *name; + WCHAR *encname; + HRESULT hr;
+ TRACE("(%p %d)!\n", view, row);
Leftover '!'
+ name = msi_string_lookup( db->strings, db->streams[row].str_index, NULL ); + if (!(encname = encode_streamname( FALSE, name ))) return ERROR_OUTOFMEMORY; + hr = IStorage_DestroyElement( db->storage, encname ); + msi_free( encname ); + if (FAILED( hr )) + return ERROR_FUNCTION_FAILED; + hr = IStream_Release( db->streams[row].stream ); + if (FAILED( hr )) + return ERROR_FUNCTION_FAILED;
I guess this works in transacted mode but in non-transacted mode the stream is invalid after the call to IStorage_DestroyElement. That may make the IStream_Release call fail. There could be other references to this stream as well. What does native do in that case?