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