ole32: Invalidate open storage objects that outlive their parent.

This commit is contained in:
Vincent Povirk 2009-11-19 13:42:47 -06:00 committed by Alexandre Julliard
parent 3cd2a80eda
commit d3c0a3a829
3 changed files with 76 additions and 8 deletions

View File

@ -77,9 +77,11 @@ static const char rootEntryName[] = "Root Entry";
struct StorageInternalImpl struct StorageInternalImpl
{ {
struct StorageBaseImpl base; 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; typedef struct StorageInternalImpl StorageInternalImpl;
@ -111,6 +113,7 @@ static BOOL StorageImpl_ReadDWordFromBigBlock( StorageImpl* This,
ULONG blockIndex, ULONG offset, DWORD* value); ULONG blockIndex, ULONG offset, DWORD* value);
static BOOL StorageBaseImpl_IsStreamOpen(StorageBaseImpl * stg, DirRef streamEntry); static BOOL StorageBaseImpl_IsStreamOpen(StorageBaseImpl * stg, DirRef streamEntry);
static void StorageInternalImpl_Invalidate( StorageInternalImpl *This );
/* OLESTREAM memory structure to use for Get and Put Routines */ /* OLESTREAM memory structure to use for Get and Put Routines */
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
@ -428,6 +431,12 @@ static HRESULT WINAPI StorageBaseImpl_OpenStream(
goto end; goto end;
} }
if (!This->ancestorStorage)
{
res = STG_E_REVERTED;
goto end;
}
/* /*
* Check that we're compatible with the parent's storage mode, but * Check that we're compatible with the parent's storage mode, but
* only if we are not in transacted mode * only if we are not in transacted mode
@ -544,6 +553,9 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage(
goto end; goto end;
} }
if (!This->ancestorStorage)
return STG_E_REVERTED;
/* /*
* Check that we're compatible with the parent's storage mode, * Check that we're compatible with the parent's storage mode,
* but only if we are not transacted * but only if we are not transacted
@ -578,6 +590,8 @@ static HRESULT WINAPI StorageBaseImpl_OpenStorage(
StorageBaseImpl_AddRef(*ppstg); StorageBaseImpl_AddRef(*ppstg);
list_add_tail(&This->storageHead, &newStorage->ParentListEntry);
res = S_OK; res = S_OK;
goto end; goto end;
} }
@ -617,6 +631,9 @@ static HRESULT WINAPI StorageBaseImpl_EnumElements(
if ( (This==0) || (ppenum==0)) if ( (This==0) || (ppenum==0))
return E_INVALIDARG; return E_INVALIDARG;
if (!This->ancestorStorage)
return STG_E_REVERTED;
newEnum = IEnumSTATSTGImpl_Construct( newEnum = IEnumSTATSTGImpl_Construct(
This->ancestorStorage, This->ancestorStorage,
This->storageDirEntry); This->storageDirEntry);
@ -659,6 +676,12 @@ static HRESULT WINAPI StorageBaseImpl_Stat(
goto end; goto end;
} }
if (!This->ancestorStorage)
{
res = STG_E_REVERTED;
goto end;
}
readSuccessful = StorageImpl_ReadDirEntry( readSuccessful = StorageImpl_ReadDirEntry(
This->ancestorStorage, This->ancestorStorage,
This->storageDirEntry, This->storageDirEntry,
@ -708,6 +731,9 @@ static HRESULT WINAPI StorageBaseImpl_RenameElement(
TRACE("(%p, %s, %s)\n", TRACE("(%p, %s, %s)\n",
iface, debugstr_w(pwcsOldName), debugstr_w(pwcsNewName)); iface, debugstr_w(pwcsOldName), debugstr_w(pwcsNewName));
if (!This->ancestorStorage)
return STG_E_REVERTED;
currentEntryRef = findElement(This->ancestorStorage, currentEntryRef = findElement(This->ancestorStorage,
This->storageDirEntry, This->storageDirEntry,
pwcsNewName, pwcsNewName,
@ -801,6 +827,9 @@ static HRESULT WINAPI StorageBaseImpl_CreateStream(
if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE) if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE)
return STG_E_INVALIDFLAG; return STG_E_INVALIDFLAG;
if (!This->ancestorStorage)
return STG_E_REVERTED;
/* /*
* As documented. * As documented.
*/ */
@ -929,6 +958,9 @@ static HRESULT WINAPI StorageBaseImpl_SetClass(
TRACE("(%p, %p)\n", iface, clsid); TRACE("(%p, %p)\n", iface, clsid);
if (!This->ancestorStorage)
return STG_E_REVERTED;
success = StorageImpl_ReadDirEntry(This->ancestorStorage, success = StorageImpl_ReadDirEntry(This->ancestorStorage,
This->storageDirEntry, This->storageDirEntry,
&currentEntry); &currentEntry);
@ -992,6 +1024,9 @@ static HRESULT WINAPI StorageBaseImpl_CreateStorage(
return STG_E_INVALIDFLAG; return STG_E_INVALIDFLAG;
} }
if (!This->ancestorStorage)
return STG_E_REVERTED;
/* /*
* Check that we're compatible with the parent's storage mode * Check that we're compatible with the parent's storage mode
*/ */
@ -1731,6 +1766,9 @@ static HRESULT WINAPI StorageBaseImpl_DestroyElement(
if (pwcsName==NULL) if (pwcsName==NULL)
return STG_E_INVALIDPOINTER; return STG_E_INVALIDPOINTER;
if (!This->ancestorStorage)
return STG_E_REVERTED;
if ( STGM_ACCESS_MODE( This->openFlags ) == STGM_READ ) if ( STGM_ACCESS_MODE( This->openFlags ) == STGM_READ )
return STG_E_ACCESSDENIED; return STG_E_ACCESSDENIED;
@ -1841,13 +1879,19 @@ static void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg)
{ {
struct list *cur, *cur2; struct list *cur, *cur2;
StgStreamImpl *strm=NULL; StgStreamImpl *strm=NULL;
StorageInternalImpl *childstg=NULL;
LIST_FOR_EACH_SAFE(cur, cur2, &stg->strmHead) { LIST_FOR_EACH_SAFE(cur, cur2, &stg->strmHead) {
strm = LIST_ENTRY(cur,StgStreamImpl,StrmListEntry); 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; strm->parentStorage = NULL;
list_remove(cur); 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] */ DWORD grfMask) /* [in] */
{ {
StorageBaseImpl* const This = (StorageBaseImpl*)iface; StorageBaseImpl* const This = (StorageBaseImpl*)iface;
if (!This->ancestorStorage)
return STG_E_REVERTED;
This->stateBits = (This->stateBits & ~grfMask) | (grfStateBits & grfMask); This->stateBits = (This->stateBits & ~grfMask) | (grfStateBits & grfMask);
return S_OK; return S_OK;
} }
@ -2170,6 +2218,8 @@ static HRESULT StorageImpl_Construct(
list_init(&This->base.strmHead); list_init(&This->base.strmHead);
list_init(&This->base.storageHead);
This->base.lpVtbl = &Storage32Impl_Vtbl; This->base.lpVtbl = &Storage32Impl_Vtbl;
This->base.pssVtbl = &IPropertySetStorage_Vtbl; This->base.pssVtbl = &IPropertySetStorage_Vtbl;
This->base.v_destructor = StorageImpl_Destroy; This->base.v_destructor = StorageImpl_Destroy;
@ -3512,11 +3562,25 @@ SmallBlockChainStream* Storage32Impl_BigBlocksToSmallBlocks(
return SmallBlockChainStream_Construct(This, NULL, streamEntryRef); 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) static void StorageInternalImpl_Destroy( StorageBaseImpl *iface)
{ {
StorageInternalImpl* This = (StorageInternalImpl*) iface; StorageInternalImpl* This = (StorageInternalImpl*) iface;
StorageBaseImpl_DeleteAll(&This->base); StorageInternalImpl_Invalidate(This);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
@ -3975,11 +4039,10 @@ static StorageInternalImpl* StorageInternalImpl_Construct(
if (newStorage!=0) if (newStorage!=0)
{ {
/*
* Initialize the stream list
*/
list_init(&newStorage->base.strmHead); list_init(&newStorage->base.strmHead);
list_init(&newStorage->base.storageHead);
/* /*
* Initialize the virtual function table. * Initialize the virtual function table.
*/ */

View File

@ -201,6 +201,11 @@ struct StorageBaseImpl
struct list strmHead; struct list strmHead;
/*
* Storage tracking list
*/
struct list storageHead;
/* /*
* Reference count of this object * Reference count of this object
*/ */

View File

@ -1335,10 +1335,10 @@ static void test_parent_free(void)
IStream_Release(stm); IStream_Release(stm);
r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME); 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); 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); IStorage_Release(stg3);
} }