[RESENT] Split patch part 2 for reference counting bug in storage32 (bug #4436 part 2)

Dr J A Gow J.A.Gow at furrybubble.co.uk
Mon Feb 20 14:07:49 CST 2006


FROM:  Dr J A Gow
PATCH: Fixes up permissions when opening streams in storage objects
        when storage object has been opened in transacted mode. This
        fixes the second part of the bug 4436:
           - Stream opening when storage was opened in transacted mode
           - Adds conformance test for stream opening in transacted
             mode


Index: wine/dlls/ole32/stg_stream.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/stg_stream.c,v
retrieving revision 1.29
diff -u -p -r1.29 stg_stream.c
--- wine/dlls/ole32/stg_stream.c	3 Jan 2006 12:40:12 -0000	1.29
+++ wine/dlls/ole32/stg_stream.c	19 Feb 2006 16:42:43 -0000
@@ -58,8 +58,21 @@ static void StgStreamImpl_Destroy(StgStr

    /*
     * Release the reference we are holding on the parent storage.
+   * IStorage_Release((IStorage*)This->parentStorage);
+   *
+   * No, don't do this. Some apps call IStorage_Release without
+   * calling IStream_Release first. If we grab a reference the
+   * file is not closed, and the app fails when it tries to
+   * reopen the file (Easy-PC, for example). Just inform the
+   * storage that we have closed the stream
     */
-  IStorage_Release((IStorage*)This->parentStorage);
+
+  if(This->parentStorage) {
+
+    StorageBaseImpl_RemoveStream(This->parentStorage, This);
+
+  }
+
    This->parentStorage = 0;

    /*
@@ -447,6 +460,14 @@ static HRESULT WINAPI StgStreamImpl_Seek
  	iface, dlibMove.u.LowPart, dwOrigin, plibNewPosition);

    /*
+   * fail if the stream has no parent (as does windows)
+   */
+
+  if(!(This->parentStorage)) {
+    return STG_E_REVERTED;
+  }
+
+  /*
     * The caller is allowed to pass in NULL as the new position return value.
     * If it happens, we assign it to a dynamic variable to avoid special cases
     * in the code below.
@@ -506,6 +527,10 @@ static HRESULT WINAPI StgStreamImpl_SetS

    TRACE("(%p, %ld)\n", iface, libNewSize.u.LowPart);

+  if(!This->parentStorage) {
+    return STG_E_REVERTED;
+  }
+
    /*
     * As documented.
     */
@@ -609,6 +634,8 @@ static HRESULT WINAPI StgStreamImpl_Copy
  				    ULARGE_INTEGER* pcbRead,      /* [out] */
  				    ULARGE_INTEGER* pcbWritten)   /* [out] */
  {
+  StgStreamImpl* const This=(StgStreamImpl*)iface;
+
    HRESULT        hr = S_OK;
    BYTE           tmpBuffer[128];
    ULONG          bytesRead, bytesWritten, copySize;
@@ -621,6 +648,11 @@ static HRESULT WINAPI StgStreamImpl_Copy
    /*
     * Sanity check
     */
+
+  if(!This->parentStorage) {
+    return STG_E_REVERTED;
+  }
+
    if ( pstm == 0 )
      return STG_E_INVALIDPOINTER;

@@ -691,6 +723,11 @@ static HRESULT WINAPI StgStreamImpl_Comm
  		  IStream*      iface,
  		  DWORD           grfCommitFlags)  /* [in] */
  {
+  StgStreamImpl* const This=(StgStreamImpl*)iface;
+
+  if(!This->parentStorage) {
+    return STG_E_REVERTED;
+  }
    return S_OK;
  }

@@ -714,6 +751,12 @@ static HRESULT WINAPI StgStreamImpl_Lock
  					ULARGE_INTEGER cb,          /* [in] */
  					DWORD          dwLockType)  /* [in] */
  {
+  StgStreamImpl* const This=(StgStreamImpl*)iface;
+
+  if(!This->parentStorage) {
+    return STG_E_REVERTED;
+  }
+
    FIXME("not implemented!\n");
    return E_NOTIMPL;
  }
@@ -724,6 +767,12 @@ static HRESULT WINAPI StgStreamImpl_Unlo
  					  ULARGE_INTEGER cb,          /* [in] */
  					  DWORD          dwLockType)  /* [in] */
  {
+  StgStreamImpl* const This=(StgStreamImpl*)iface;
+
+  if(!This->parentStorage) {
+    return STG_E_REVERTED;
+  }
+
    FIXME("not implemented!\n");
    return E_NOTIMPL;
  }
@@ -747,6 +796,14 @@ static HRESULT WINAPI StgStreamImpl_Stat
    BOOL         readSucessful;

    /*
+   * if stream has no parent, return STG_E_REVERTED
+   */
+
+  if(!This->parentStorage) {
+	return STG_E_REVERTED;
+  }
+
+  /*
     * Read the information from the property.
     */
    readSucessful = StorageImpl_ReadProperty(This->parentStorage->ancestorStorage,
@@ -791,6 +848,11 @@ static HRESULT WINAPI StgStreamImpl_Clon
    /*
     * Sanity check
     */
+
+  if(!This->parentStorage) {
+    return STG_E_REVERTED;
+  }
+
    if ( ppstm == 0 )
      return STG_E_INVALIDPOINTER;

@@ -858,12 +920,19 @@ StgStreamImpl* StgStreamImpl_Construct(
      newStream->lpVtbl    = &StgStreamImpl_Vtbl;
      newStream->ref       = 0;

+    newStream->parentStorage = parentStorage;
+
      /*
       * We want to nail-down the reference to the storage in case the
       * stream out-lives the storage in the client application.
+     *
+     * -- IStorage_AddRef((IStorage*)newStream->parentStorage);
+     *
+     * No, don't do this. Some apps call IStorage_Release without
+     * calling IStream_Release first. If we grab a reference the
+     * file is not closed, and the app fails when it tries to
+     * reopen the file (Easy-PC, for example)
       */
-    newStream->parentStorage = parentStorage;
-    IStorage_AddRef((IStorage*)newStream->parentStorage);

      newStream->grfMode = grfMode;
      newStream->ownerProperty = ownerProperty;
Index: wine/dlls/ole32/storage32.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/storage32.c,v
retrieving revision 1.99
diff -u -p -r1.99 storage32.c
--- wine/dlls/ole32/storage32.c	6 Jan 2006 20:51:54 -0000	1.99
+++ wine/dlls/ole32/storage32.c	19 Feb 2006 16:42:50 -0000
@@ -390,6 +393,12 @@ HRESULT WINAPI StorageBaseImpl_OpenStrea
         */
        IStream_AddRef(*ppstm);

+      /*
+       * add us to the storage's list of active streams
+       */
+
+       StorageBaseImpl_AddStream(This,newStream);
+
        res = S_OK;
        goto end;
      }
@@ -970,6 +985,11 @@ HRESULT WINAPI StorageBaseImpl_CreateStr
       * the reference.
       */
      IStream_AddRef(*ppstm);
+
+    /* add us to the storage's list of active streams
+     */
+    StorageBaseImpl_AddStream(This,newStream);
+
    }
    else
    {
@@ -1788,8 +1808,35 @@ HRESULT WINAPI StorageImpl_Stat( IStorag
    return result;
  }

+ /******************************************************************************
+ * Internal stream list handlers					
+ */

+void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm)
+{
+  TRACE("Stream added (stg=%p strm=%p)\n", stg, strm);
+  list_add_tail(&stg->strmHead,&strm->StrmListEntry);
+}

+void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm)
+{
+  TRACE("Stream removed (stg=%p strm=%p)\n", stg,strm);
+  list_remove(&(strm->StrmListEntry));
+}
+
+void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg)
+{
+  struct list *    cur;
+  struct list *    cur2;
+  StgStreamImpl *  strm=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);
+    strm->parentStorage = NULL;	
+    list_remove(cur);
+  }
+}
  /*********************************************************************
   *
   * Internal Method
@@ -2247,6 +2294,12 @@ HRESULT StorageImpl_Construct(
    memset(This, 0, sizeof(StorageImpl));

    /*
+   * Initialize stream list
+   */
+
+  list_init(&This->base.strmHead);
+
+  /*
     * Initialize the virtual function table.
     */
    This->base.lpVtbl = &Storage32Impl_Vtbl;
@@ -2439,6 +2492,8 @@ void StorageImpl_Destroy(StorageBaseImpl
    StorageImpl *This = (StorageImpl*) iface;
    TRACE("(%p)\n", This);

+  StorageBaseImpl_DeleteAll(&This->base);
+
    HeapFree(GetProcessHeap(), 0, This->pwcsName);

    BlockChainStream_Destroy(This->smallBlockRootChain);
@@ -4104,6 +4159,12 @@ StorageInternalImpl* StorageInternalImpl
      memset(newStorage, 0, sizeof(StorageInternalImpl));

      /*
+     * Initialize the stream list
+     */
+
+    list_init(&newStorage->base.strmHead);
+
+    /*
       * Initialize the virtual function table.
       */
      newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;
Index: wine/dlls/ole32/storage32.h
===================================================================
RCS file: /home/wine/wine/dlls/ole32/storage32.h,v
retrieving revision 1.27
diff -u -p -r1.27 storage32.h
--- wine/dlls/ole32/storage32.h	22 Dec 2005 17:12:52 -0000	1.27
+++ wine/dlls/ole32/storage32.h	19 Feb 2006 16:42:51 -0000
@@ -37,6 +37,7 @@
  #include "objbase.h"
  #include "winreg.h"
  #include "winternl.h"
+#include <wine/list.h>

  /*
   * Definitions for the file format offsets.
@@ -220,6 +221,12 @@ struct StorageBaseImpl
    const IPropertySetStorageVtbl *pssVtbl; /* interface for adding a properties stream */

    /*
+   * Stream tracking list
+   */
+
+  struct list strmHead;
+
+  /*
     * Reference count of this object
     */
    LONG ref;
@@ -246,6 +253,13 @@ struct StorageBaseImpl
    DWORD openFlags;
  };

+/****************************************************************************
+ * StorageBaseImpl stream list handlers
+ */
+
+void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm);
+void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm);
+void StorageBaseImpl_DeleteAll(StorageBaseImpl * stg);

  /****************************************************************************
   * Storage32Impl definitions.
@@ -485,6 +499,12 @@ struct StgStreamImpl
  			 * since we want to cast this to an IStream pointer */

    /*
+   * We are an entry in the storage object's stream handler list
+   */
+
+  struct list StrmListEntry;
+
+  /*
     * Reference count
     */
    LONG		     ref;



More information about the wine-patches mailing list