ole32: Invalidate open storage objects that outlive their parent.
This commit is contained in:
parent
3cd2a80eda
commit
d3c0a3a829
|
@ -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,
|
||||||
¤tEntry);
|
¤tEntry);
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue