Andrew Eikum : ole32: Don't fail when constants are 'incorrect'.

Alexandre Julliard julliard at winehq.org
Tue Sep 8 08:53:38 CDT 2009


Module: wine
Branch: master
Commit: 968126c2312378dd44cb28d4a9aac527668e53fd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=968126c2312378dd44cb28d4a9aac527668e53fd

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Wed Sep  2 11:41:57 2009 -0500

ole32: Don't fail when constants are 'incorrect'.

---

 dlls/ole32/filemoniker.c   |   49 ++++++++++++++++++++----------
 dlls/ole32/tests/moniker.c |   70 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+), 17 deletions(-)

diff --git a/dlls/ole32/filemoniker.c b/dlls/ole32/filemoniker.c
index e9fd4ca..9decfaf 100644
--- a/dlls/ole32/filemoniker.c
+++ b/dlls/ole32/filemoniker.c
@@ -198,9 +198,9 @@ FileMonikerImpl_Load(IMoniker* iface, IStream* pStm)
 
     TRACE("(%p,%p)\n",iface,pStm);
 
-    /* first WORD must be 0 */
+    /* first WORD */
     res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
-    if (bread!=sizeof(WORD) || wbuffer!=0)
+    if (bread!=sizeof(WORD))
     {
         WARN("Couldn't read 0 word\n");
         goto fail;
@@ -229,18 +229,26 @@ FileMonikerImpl_Load(IMoniker* iface, IStream* pStm)
         goto fail;
     }
 
-    /* read the first constant */
-    IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
-    if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF)
+    /* read the unknown value */
+    IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
+    if (bread != sizeof(WORD))
     {
-        WARN("Couldn't read 0xDEADFFFF constant\n");
+        WARN("Couldn't read unknown value\n");
+        goto fail;
+    }
+
+    /* read the DEAD constant */
+    IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
+    if (bread != sizeof(WORD))
+    {
+        WARN("Couldn't read DEAD constant\n");
         goto fail;
     }
 
     for(i=0;i<5;i++)
     {
         res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
-        if (bread!=sizeof(DWORD) || dwbuffer!=0)
+        if (bread!=sizeof(DWORD))
         {
             WARN("Couldn't read 0 padding\n");
             goto fail;
@@ -320,18 +328,20 @@ FileMonikerImpl_Load(IMoniker* iface, IStream* pStm)
  * of Windows have minor variations.
  *
  * Data which must be written on stream is:
- * 1) WORD constant:zero
+ * 1) WORD constant: zero (not validated by Windows)
  * 2) length of the path string ("\0" included)
  * 3) path string type A
- * 4) DWORD constant : 0xDEADFFFF
- * 5) five DWORD constant: zero
- * 6) If we're only writing the multibyte version, 
+ * 4) Unknown WORD value: Frequently 0xFFFF, but not always. If set very large,
+ *     Windows returns E_OUTOFMEMORY
+ * 5) WORD Constant: 0xDEAD (not validated by Windows)
+ * 6) five DWORD constant: zero (not validated by Windows)
+ * 7) If we're only writing the multibyte version,
  *     write a zero DWORD and finish.
  *
- * 7) DWORD: double-length of the path string type W ("\0" not
+ * 8) DWORD: double-length of the path string type W ("\0" not
  *    included)
- * 8) WORD constant: 0x3
- * 9) filePath unicode string.
+ * 9) WORD constant: 0x3
+ * 10) filePath unicode string.
  *
  */
 static HRESULT WINAPI
@@ -344,7 +354,8 @@ FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
     CHAR*    filePathA;
     DWORD bytesA, bytesW, len;
 
-    static const DWORD DEADFFFF = 0xDEADFFFF;  /* Constants */
+    static const WORD FFFF = 0xFFFF; /* Constants */
+    static const WORD DEAD = 0xDEAD;
     static const DWORD ZERO     = 0;
     static const WORD  THREE    = 0x3;
 
@@ -374,8 +385,12 @@ FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
     HeapFree(GetProcessHeap(),0,filePathA);
     if (FAILED(res)) return res;
 
-    /* write a DWORD 0xDEADFFFF */
-    res=IStream_Write(pStm,&DEADFFFF,sizeof(DWORD),NULL);
+    /* write a WORD 0xFFFF */
+    res=IStream_Write(pStm,&FFFF,sizeof(WORD),NULL);
+    if (FAILED(res)) return res;
+
+    /* write a WORD 0xDEAD */
+    res=IStream_Write(pStm,&DEAD,sizeof(WORD),NULL);
     if (FAILED(res)) return res;
 
     /* write 5 zero DWORDs */
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index b172377..d27f766 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -1867,6 +1867,75 @@ static void test_bind_context(void)
     ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
 }
 
+static void test_save_load_filemoniker(void)
+{
+    IMoniker* pMk;
+    IStream* pStm;
+    HRESULT hr;
+    ULARGE_INTEGER size;
+    LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
+    DWORD some_val = 0xFEDCBA98;
+    int i;
+
+    /* see FileMonikerImpl_Save docs */
+    zero_pos.u.LowPart = 0;
+    dead_pos.u.LowPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
+    nulls_pos.u.LowPart = dead_pos.u.LowPart + sizeof(WORD);
+
+    /* create the stream we're going to write to */
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
+    ok_ole_success(hr, "CreateStreamOnHGlobal");
+
+    size.u.LowPart = 128;
+    hr = IStream_SetSize(pStm, size);
+    ok_ole_success(hr, "IStream_SetSize");
+
+    /* create and save a moniker */
+    hr = CreateFileMoniker(wszFileName1, &pMk);
+    ok_ole_success(hr, "CreateFileMoniker");
+
+    hr = IMoniker_Save(pMk, pStm, TRUE);
+    ok_ole_success(hr, "IMoniker_Save");
+
+    hr = IMoniker_Release(pMk);
+    ok_ole_success(hr, "IMoniker_Release");
+
+    /* overwrite the constants with various values */
+    hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
+    ok_ole_success(hr, "IStream_Seek");
+    hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
+    ok_ole_success(hr, "IStream_Write");
+
+    hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
+    ok_ole_success(hr, "IStream_Seek");
+    hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
+    ok_ole_success(hr, "IStream_Write");
+
+    hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
+    ok_ole_success(hr, "IStream_Seek");
+    for(i = 0; i < 5; ++i){
+        hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
+        ok_ole_success(hr, "IStream_Write");
+    }
+
+    /* go back to the start of the stream */
+    hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
+    ok_ole_success(hr, "IStream_Seek");
+
+    /* create a new moniker and load into it */
+    hr = CreateFileMoniker(wszFileName1, &pMk);
+    ok_ole_success(hr, "CreateFileMoniker");
+
+    hr = IMoniker_Load(pMk, pStm);
+    ok_ole_success(hr, "IMoniker_Load");
+
+    hr = IMoniker_Release(pMk);
+    ok_ole_success(hr, "IMoniker_Release");
+
+    hr = IStream_Release(pStm);
+    ok_ole_success(hr, "IStream_Release");
+}
+
 START_TEST(moniker)
 {
     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
@@ -1880,6 +1949,7 @@ START_TEST(moniker)
     test_anti_moniker();
     test_generic_composite_moniker();
     test_pointer_moniker();
+    test_save_load_filemoniker();
 
     /* FIXME: test moniker creation funcs and parsing other moniker formats */
 




More information about the wine-cvs mailing list