From 18791f4ab7eec1fd02f45c8e18a0ac03f88e4448 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 19 Nov 2009 13:42:47 -0600 Subject: [PATCH 2/5] ole32: Invalidate open storage objects that outlive their parent. --- dlls/ole32/storage32.c | 75 ++++++++++++++++++++++++++++++++++++++--- dlls/ole32/storage32.h | 5 +++ dlls/ole32/tests/storage32.c | 4 +- 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index 8613aa8..269f611 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -77,9 +77,11 @@ static const char rootEntryName[] = "Root Entry"; struct StorageInternalImpl { struct StorageBaseImpl base; + /* - * There is no specific data for this class. + * Entry in the parent's stream tracking list */ + struct list ParentListEntry; }; typedef struct StorageInternalImpl StorageInternalImpl; @@ -111,6 +113,7 @@ static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This, ULONG blockIndex, ULONG offset, DWORD* value); static BOOL StorageBaseImpl_IsStreamOpen(StorageBaseImpl * stg, DirRef streamEntry); +static void StorageInternalImpl_Invalidate( StorageInternalImpl *This ); /* OLESTREAM memory structure to use for Get and Put Routines */ /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ @@ -428,6 +431,12 @@ static HRESULT WINAPI StorageBaseImpl_OpenStream( goto end; } + if (!This->ancestorStorage) + { + res = STG_E_REVERTED; + goto end; + } + /* * Check that we're compatible with the parent's storage mode, but * only if we are not in transacted mode @@ -544,6 +553,9 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage( goto end; } + if (!This->ancestorStorage) + return STG_E_REVERTED; + /* * Check that we're compatible with the parent's storage mode, * but only if we are not transacted @@ -578,6 +590,8 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage( StorageBaseImpl_AddRef(*ppstg); + list_add_tail(&This->storageHead, &newStorage->ParentListEntry); + res = S_OK; goto end; } @@ -617,6 +631,9 @@ static HRESULT WINAPI StorageBaseImpl_EnumElements( if ( (This==0) || (ppenum==0)) return E_INVALIDARG; + if (!This->ancestorStorage) + return STG_E_REVERTED; + newEnum = IEnumSTATSTGImpl_Construct( This->ancestorStorage, This->storageDirEntry); @@ -659,6 +676,12 @@ static HRESULT WINAPI StorageBaseImpl_Stat( goto end; } + if (!This->ancestorStorage) + { + res = STG_E_REVERTED; + goto end; + } + readSuccessful = StorageImpl_ReadDirEntry( This->ancestorStorage, This->storageDirEntry, @@ -708,6 +731,9 @@ static HRESULT WINAPI StorageBaseImpl_RenameElement( TRACE("(%p, %s, %s)\n", iface, debugstr_w(pwcsOldName), debugstr_w(pwcsNewName)); + if (!This->ancestorStorage) + return STG_E_REVERTED; + currentEntryRef = findElement(This->ancestorStorage, This->storageDirEntry, pwcsNewName, @@ -801,6 +827,9 @@ static HRESULT WINAPI StorageBaseImpl_CreateStream( if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE) return STG_E_INVALIDFLAG; + if (!This->ancestorStorage) + return STG_E_REVERTED; + /* * As documented. */ @@ -929,6 +958,9 @@ static HRESULT WINAPI StorageBaseImpl_SetClass( TRACE("(%p, %p)\n", iface, clsid); + if (!This->ancestorStorage) + return STG_E_REVERTED; + success = StorageImpl_ReadDirEntry(This->ancestorStorage, This->storageDirEntry, ¤tEntry); @@ -992,6 +1024,9 @@ static HRESULT WINAPI StorageBaseImpl_CreateStorage( return STG_E_INVALIDFLAG; } + if (!This->ancestorStorage) + return STG_E_REVERTED; + /* * Check that we're compatible with the parent's storage mode */ @@ -1731,6 +1766,9 @@ static HRESULT WINAPI StorageBaseImpl_DestroyElement( if (pwcsName==NULL) return STG_E_INVALIDPOINTER; + if (!This->ancestorStorage) + return STG_E_REVERTED; + if ( STGM_ACCESS_MODE( This->openFlags ) == STGM_READ ) return STG_E_ACCESSDENIED; @@ -1841,13 +1879,19 @@ static void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg) { struct list *cur, *cur2; StgStreamImpl *strm=NULL; + StorageInternalImpl *childstg=NULL; LIST_FOR_EACH_SAFE(cur, cur2, &stg->strmHead) { strm = LIST_ENTRY(cur,StgStreamImpl,StrmListEntry); - TRACE("Streams deleted (stg=%p strm=%p next=%p prev=%p)\n", stg,strm,cur->next,cur->prev); + TRACE("Streams invalidated (stg=%p strm=%p next=%p prev=%p)\n", stg,strm,cur->next,cur->prev); strm->parentStorage = NULL; list_remove(cur); } + + LIST_FOR_EACH_SAFE(cur, cur2, &stg->storageHead) { + childstg = LIST_ENTRY(cur,StorageInternalImpl,ParentListEntry); + StorageInternalImpl_Invalidate( childstg ); + } } @@ -2120,6 +2164,10 @@ static HRESULT WINAPI StorageBaseImpl_SetStateBits( DWORD grfMask) /* [in] */ { StorageBaseImpl* const This = (StorageBaseImpl*)iface; + + if (!This->ancestorStorage) + return STG_E_REVERTED; + This->stateBits = (This->stateBits & ~grfMask) | (grfStateBits & grfMask); return S_OK; } @@ -2170,6 +2218,8 @@ static HRESULT StorageImpl_Construct( list_init(&This->base.strmHead); + list_init(&This->base.storageHead); + This->base.lpVtbl = &Storage32Impl_Vtbl; This->base.pssVtbl = &IPropertySetStorage_Vtbl; This->base.v_destructor = StorageImpl_Destroy; @@ -3512,11 +3562,25 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks( return SmallBlockChainStream_Construct(This, NULL, streamEntryRef); } +static void StorageInternalImpl_Invalidate( StorageInternalImpl *This ) +{ + if (This->base.ancestorStorage) + { + TRACE("Storage invalidated (stg=%p)\n", This); + + This->base.ancestorStorage = NULL; + + StorageBaseImpl_DeleteAll(&This->base); + + list_remove(&This->ParentListEntry); + } +} + static void StorageInternalImpl_Destroy( StorageBaseImpl *iface) { StorageInternalImpl* This = (StorageInternalImpl*) iface; - StorageBaseImpl_DeleteAll(&This->base); + StorageInternalImpl_Invalidate(This); HeapFree(GetProcessHeap(), 0, This); } @@ -3975,11 +4039,10 @@ static StorageInternalImpl* StorageInternalImpl_Construct( if (newStorage!=0) { - /* - * Initialize the stream list - */ list_init(&newStorage->base.strmHead); + list_init(&newStorage->base.storageHead); + /* * Initialize the virtual function table. */ diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index 8060acf..4a953c1 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -202,6 +202,11 @@ struct StorageBaseImpl struct list strmHead; /* + * Storage tracking list + */ + struct list storageHead; + + /* * Reference count of this object */ LONG ref; diff --git a/dlls/ole32/tests/storage32.c b/dlls/ole32/tests/storage32.c index 2e80b6e..d11f179 100644 --- a/dlls/ole32/tests/storage32.c +++ b/dlls/ole32/tests/storage32.c @@ -1335,10 +1335,10 @@ static void test_parent_free(void) IStream_Release(stm); r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME); - todo_wine ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); + ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); r = IStorage_SetStateBits(stg3, 1, 1); - todo_wine ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); + ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r); IStorage_Release(stg3); } -- 1.6.3.3