PATCH: more 16bit ole

Marcus Meissner marcus at jet.franken.de
Fri Aug 5 15:41:12 CDT 2005


Hi,

Testing a 16bit OLE using application I had to fix some 16bit OLE things.

The 16bit compound storage handling now understands ILockBytes interfaces.
(Actually it should be ported to use the 32bit one instead of doing it the
hack approach it currently is.)
And some stubs / small functions added.

Now it wants to do OLELOAD :/

Changelog:
	Implemented ILockBytes16 (memorystream) support for the 16bit compound
	storage implementation.
	Added ReadClassStg, OleDoAutoConvert, GetConvertStg implementations/stubs.

Index: dlls/ole32/ole2.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/ole2.c,v
retrieving revision 1.70
diff -u -r1.70 ole2.c
--- dlls/ole32/ole2.c	22 Jul 2005 18:29:19 -0000	1.70
+++ dlls/ole32/ole2.c	5 Aug 2005 20:38:19 -0000
@@ -2328,6 +2328,15 @@
     return E_NOTIMPL;
 }
 
+/******************************************************************************
+ *              OleDoAutoConvert        [OLE2.@]
+ */
+HRESULT WINAPI OleDoAutoConvert16(IStorage *pStg, LPCLSID pClsidNew)
+{
+    FIXME("(%p,%p) : stub\n",pStg,pClsidNew);
+    return E_NOTIMPL;
+}
+
 /***********************************************************************
  *           OLE_FreeClipDataArray   [internal]
  *
Index: dlls/ole32/ole2.spec
===================================================================
RCS file: /home/wine/wine/dlls/ole32/ole2.spec,v
retrieving revision 1.10
diff -u -r1.10 ole2.spec
--- dlls/ole32/ole2.spec	22 Jul 2005 18:29:39 -0000	1.10
+++ dlls/ole32/ole2.spec	5 Aug 2005 20:38:19 -0000
@@ -15,7 +15,7 @@
 #15 ___EXPORTEDSTUB
 16 stub OLEISRUNNING
 17 stub OLELOCKRUNNING
-18 stub READCLASSSTG
+18 pascal ReadClassStg(segptr ptr) ReadClassStg16
 19 stub WRITECLASSSTG
 20 stub READCLASSSTM
 21 stub WRITECLASSSTM
@@ -74,10 +74,10 @@
 76 pascal -ret16 OleFlushClipboard() OleFlushClipboard16
 77 stub OLEISCURRENTCLIPBOARD
 78 stub OLETRANSLATEACCELERATOR
-79 stub OLEDOAUTOCONVERT
+79 pascal OleDoAutoConvert(ptr ptr) OleDoAutoConvert16
 80 stub OLEGETAUTOCONVERT
 81 stub OLESETAUTOCONVERT
-82 stub GETCONVERTSTG
+82 pascal GETCONVERTSTG(ptr) GetConvertStg16
 83 stub SETCONVERTSTG
 84 stub CREATESTREAMONHGLOBAL
 85 stub GETHGLOBALFROMSTREAM
Index: dlls/ole32/storage.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/storage.c,v
retrieving revision 1.47
diff -u -r1.47 storage.c
--- dlls/ole32/storage.c	22 Jul 2005 09:03:29 -0000	1.47
+++ dlls/ole32/storage.c	5 Aug 2005 20:38:20 -0000
@@ -89,7 +89,7 @@
 
 #define SMALLBLOCKS_PER_BIGBLOCK	(BIGSIZE/SMALLSIZE)
 
-#define READ_HEADER	STORAGE_get_big_block(hf,-1,(LPBYTE)&sth);assert(!memcmp(STORAGE_magic,sth.magic,sizeof(STORAGE_magic)));
+#define READ_HEADER(str)	STORAGE_get_big_block(str,-1,(LPBYTE)&sth);assert(!memcmp(STORAGE_magic,sth.magic,sizeof(STORAGE_magic)));
 static IStorage16Vtbl stvt16;
 static const IStorage16Vtbl *segstvt16 = NULL;
 static IStream16Vtbl strvt16;
@@ -319,6 +319,24 @@
  * deeper (but never shallower) tree.
  */
 
+typedef struct {
+	HANDLE		hf;
+	SEGPTR		lockbytes;
+} stream_access16;
+/* --- IStorage16 implementation struct */
+
+typedef struct
+{
+        /* IUnknown fields */
+        const IStorage16Vtbl           *lpVtbl;
+        LONG                            ref;
+        /* IStorage16 fields */
+        SEGPTR                          thisptr; /* pointer to this struct as segmented */
+        struct storage_pps_entry        stde;
+        int                             ppsent;
+	stream_access16			str;
+} IStorage16Impl;
+
 
 /******************************************************************************
  *		STORAGE_get_big_block	[Internal]
@@ -326,22 +344,80 @@
  * Reading OLE compound storage
  */
 static BOOL
-STORAGE_get_big_block(HANDLE hf,int n,BYTE *block)
+STORAGE_get_big_block(stream_access16 *str,int n,BYTE *block)
 {
     DWORD result;
 
     assert(n>=-1);
-    if ((SetFilePointer( hf, (n+1)*BIGSIZE, NULL,
-                         SEEK_SET ) == INVALID_SET_FILE_POINTER) && GetLastError())
-    {
-        WARN(" seek failed (%ld)\n",GetLastError());
-        return FALSE;
+    if (str->hf) {
+	if ((SetFilePointer( str->hf, (n+1)*BIGSIZE, NULL,
+			     SEEK_SET ) == INVALID_SET_FILE_POINTER) && GetLastError())
+	{
+	    WARN("(%p,%d,%p), seek failed (%ld)\n",str->hf, n, block, GetLastError());
+	    return FALSE;
+	}
+	if (!ReadFile( str->hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE)
+	{
+	    WARN("(hf=%p, block size %d): read didn't read (%ld)\n",str->hf,n,GetLastError());
+	    return FALSE;
+	}
+    } else {
+	DWORD args[6];
+	HRESULT hres;
+	HANDLE16 hsig;
+	
+	args[0] = (DWORD)str->lockbytes;	/* iface */
+	args[1] = (n+1)*BIGSIZE;
+	args[2] = 0;	/* ULARGE_INTEGER offset */
+	args[3] = (DWORD)K32WOWGlobalAllocLock16( 0, BIGSIZE, &hsig ); /* sig */
+	args[4] = BIGSIZE;
+	args[5] = 0;
+
+	if (!K32WOWCallback16Ex(
+	    (DWORD)((const ILockBytes16Vtbl*)MapSL(
+			(SEGPTR)((LPLOCKBYTES16)MapSL(str->lockbytes))->lpVtbl)
+	    )->ReadAt,
+	    WCB16_PASCAL,
+	    6*sizeof(DWORD),
+	    (LPVOID)args,
+	    (LPDWORD)&hres
+	)) {
+	    ERR("CallTo16 ILockBytes16::ReadAt() failed, hres %lx\n",hres);
+	    return FALSE;
+	}
+	memcpy(block, MapSL(args[3]), BIGSIZE);
+	K32WOWGlobalUnlockFree16(args[3]);
     }
-    if (!ReadFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE)
-    {
-        WARN("(block size %d): read didn't read (%ld)\n",n,GetLastError());
-        return FALSE;
+    return TRUE;
+}
+
+static BOOL
+_ilockbytes16_writeat(SEGPTR lockbytes, DWORD offset, DWORD length, void *buffer) {
+    DWORD args[6];
+    HRESULT hres;
+
+    args[0] = (DWORD)lockbytes;	/* iface */
+    args[1] = offset;
+    args[2] = 0;	/* ULARGE_INTEGER offset */
+    args[3] = (DWORD)MapLS( buffer );
+    args[4] = length;
+    args[5] = 0;
+
+    /* THIS_ ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten); */
+
+    if (!K32WOWCallback16Ex(
+	(DWORD)((const ILockBytes16Vtbl*)MapSL(
+		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
+	)->WriteAt,
+	WCB16_PASCAL,
+	6*sizeof(DWORD),
+	(LPVOID)args,
+	(LPDWORD)&hres
+    )) {
+	ERR("CallTo16 ILockBytes16::WriteAt() failed, hres %lx\n",hres);
+	return FALSE;
     }
+    UnMapLS(args[3]);
     return TRUE;
 }
 
@@ -349,39 +425,44 @@
  * STORAGE_put_big_block [INTERNAL]
  */
 static BOOL
-STORAGE_put_big_block(HANDLE hf,int n,BYTE *block)
+STORAGE_put_big_block(stream_access16 *str,int n,BYTE *block)
 {
     DWORD result;
 
     assert(n>=-1);
-    if ((SetFilePointer( hf, (n+1)*BIGSIZE, NULL,
-                         SEEK_SET ) == INVALID_SET_FILE_POINTER) && GetLastError())
-    {
-        WARN("seek failed (%ld)\n",GetLastError());
-        return FALSE;
-    }
-    if (!WriteFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE)
-    {
-        WARN(" write failed (%ld)\n",GetLastError());
-        return FALSE;
+    if (str->hf) {
+	if ((SetFilePointer( str->hf, (n+1)*BIGSIZE, NULL,
+			     SEEK_SET ) == INVALID_SET_FILE_POINTER) && GetLastError())
+	{
+	    WARN("seek failed (%ld)\n",GetLastError());
+	    return FALSE;
+	}
+	if (!WriteFile( str->hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE)
+	{
+	    WARN(" write failed (%ld)\n",GetLastError());
+	    return FALSE;
+	}
+	return TRUE;
+    } else {
+	_ilockbytes16_writeat(str->lockbytes, (n+1)*BIGSIZE, BIGSIZE, block);
+	return TRUE;
     }
-    return TRUE;
 }
 
 /******************************************************************************
  * STORAGE_get_next_big_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_next_big_blocknr(HANDLE hf,int blocknr) {
+STORAGE_get_next_big_blocknr(stream_access16 *str,int blocknr) {
 	INT	bbs[BIGSIZE/sizeof(INT)];
 	struct	storage_header	sth;
 
-	READ_HEADER;
+	READ_HEADER(str);
 
 	assert(blocknr>>7<sth.num_of_bbd_blocks);
 	if (sth.bbd_list[blocknr>>7]==0xffffffff)
 		return -5;
-	if (!STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs))
+	if (!STORAGE_get_big_block(str,sth.bbd_list[blocknr>>7],(LPBYTE)bbs))
 		return -5;
 	assert(bbs[blocknr&0x7f]!=STORAGE_CHAINENTRY_FREE);
 	return bbs[blocknr&0x7f];
@@ -391,12 +472,13 @@
  * STORAGE_get_nth_next_big_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_nth_next_big_blocknr(HANDLE hf,int blocknr,int nr) {
+STORAGE_get_nth_next_big_blocknr(stream_access16 *str,int blocknr,int nr) {
 	INT	bbs[BIGSIZE/sizeof(INT)];
 	int	lastblock = -1;
 	struct storage_header sth;
 
-	READ_HEADER;
+	TRACE("(blocknr=%d, nr=%d)\n", blocknr, nr);
+	READ_HEADER(str);
 
 	assert(blocknr>=0);
 	while (nr--) {
@@ -405,7 +487,7 @@
 
 		/* simple caching... */
 		if (lastblock!=sth.bbd_list[blocknr>>7]) {
-			BOOL ret = STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs);
+			BOOL ret = STORAGE_get_big_block(str,sth.bbd_list[blocknr>>7],(LPBYTE)bbs);
 			assert(ret);
 			lastblock = sth.bbd_list[blocknr>>7];
 		}
@@ -418,16 +500,17 @@
  *		STORAGE_get_root_pps_entry	[Internal]
  */
 static BOOL
-STORAGE_get_root_pps_entry(HANDLE hf,struct storage_pps_entry *pstde) {
+STORAGE_get_root_pps_entry(stream_access16* str,struct storage_pps_entry *pstde) {
 	int	blocknr,i;
 	BYTE	block[BIGSIZE];
 	struct storage_pps_entry	*stde=(struct storage_pps_entry*)block;
 	struct storage_header sth;
 
-	READ_HEADER;
+	READ_HEADER(str);
 	blocknr = sth.root_startblock;
+	TRACE("startblock is %d\n", blocknr);
 	while (blocknr>=0) {
-		BOOL ret = STORAGE_get_big_block(hf,blocknr,block);
+		BOOL ret = STORAGE_get_big_block(str,blocknr,block);
 		assert(ret);
 		for (i=0;i<4;i++) {
 			if (!stde[i].pps_sizeofname)
@@ -437,7 +520,8 @@
 				return TRUE;
 			}
 		}
-		blocknr=STORAGE_get_next_big_blocknr(hf,blocknr);
+		blocknr=STORAGE_get_next_big_blocknr(str,blocknr);
+		TRACE("next block is %d\n", blocknr);
 	}
 	return FALSE;
 }
@@ -446,18 +530,19 @@
  * STORAGE_get_small_block [INTERNAL]
  */
 static BOOL
-STORAGE_get_small_block(HANDLE hf,int blocknr,BYTE *sblock) {
+STORAGE_get_small_block(stream_access16 *str,int blocknr,BYTE *sblock) {
 	BYTE				block[BIGSIZE];
 	int				bigblocknr;
 	struct storage_pps_entry	root;
 	BOOL ret;
 
+	TRACE("(blocknr=%d)\n", blocknr);
 	assert(blocknr>=0);
-	ret = STORAGE_get_root_pps_entry(hf,&root);
+	ret = STORAGE_get_root_pps_entry(str,&root);
 	assert(ret);
-	bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
+	bigblocknr = STORAGE_get_nth_next_big_blocknr(str,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
 	assert(bigblocknr>=0);
-	ret = STORAGE_get_big_block(hf,bigblocknr,block);
+	ret = STORAGE_get_big_block(str,bigblocknr,block);
 	assert(ret);
 
 	memcpy(sblock,((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),SMALLSIZE);
@@ -468,23 +553,24 @@
  * STORAGE_put_small_block [INTERNAL]
  */
 static BOOL
-STORAGE_put_small_block(HANDLE hf,int blocknr,BYTE *sblock) {
+STORAGE_put_small_block(stream_access16 *str,int blocknr,BYTE *sblock) {
 	BYTE				block[BIGSIZE];
 	int				bigblocknr;
 	struct storage_pps_entry	root;
 	BOOL ret;
 
 	assert(blocknr>=0);
+	TRACE("(blocknr=%d)\n", blocknr);
 
-	ret = STORAGE_get_root_pps_entry(hf,&root);
+	ret = STORAGE_get_root_pps_entry(str,&root);
 	assert(ret);
-	bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
+	bigblocknr = STORAGE_get_nth_next_big_blocknr(str,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
 	assert(bigblocknr>=0);
-	ret = STORAGE_get_big_block(hf,bigblocknr,block);
+	ret = STORAGE_get_big_block(str,bigblocknr,block);
 	assert(ret);
 
 	memcpy(((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),sblock,SMALLSIZE);
-	ret = STORAGE_put_big_block(hf,bigblocknr,block);
+	ret = STORAGE_put_big_block(str,bigblocknr,block);
 	assert(ret);
 	return TRUE;
 }
@@ -493,18 +579,19 @@
  * STORAGE_get_next_small_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_next_small_blocknr(HANDLE hf,int blocknr) {
+STORAGE_get_next_small_blocknr(stream_access16 *str,int blocknr) {
 	BYTE				block[BIGSIZE];
 	LPINT				sbd = (LPINT)block;
 	int				bigblocknr;
 	struct storage_header		sth;
 	BOOL ret;
 
-	READ_HEADER;
+	TRACE("(blocknr=%d)\n", blocknr);
+	READ_HEADER(str);
 	assert(blocknr>=0);
-	bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
+	bigblocknr = STORAGE_get_nth_next_big_blocknr(str,sth.sbd_startblock,blocknr/128);
 	assert(bigblocknr>=0);
-	ret = STORAGE_get_big_block(hf,bigblocknr,block);
+	ret = STORAGE_get_big_block(str,bigblocknr,block);
 	assert(ret);
 	assert(sbd[blocknr & 127]!=STORAGE_CHAINENTRY_FREE);
 	return sbd[blocknr & (128-1)];
@@ -514,21 +601,22 @@
  * STORAGE_get_nth_next_small_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_nth_next_small_blocknr(HANDLE hf,int blocknr,int nr) {
+STORAGE_get_nth_next_small_blocknr(stream_access16*str,int blocknr,int nr) {
 	int	lastblocknr=-1;
 	BYTE	block[BIGSIZE];
 	LPINT	sbd = (LPINT)block;
 	struct storage_header sth;
 	BOOL ret;
 
-	READ_HEADER;
+	TRACE("(blocknr=%d, nr=%d)\n", blocknr, nr);
+	READ_HEADER(str);
 	assert(blocknr>=0);
 	while ((nr--) && (blocknr>=0)) {
 		if (lastblocknr/128!=blocknr/128) {
 			int	bigblocknr;
-			bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
+			bigblocknr = STORAGE_get_nth_next_big_blocknr(str,sth.sbd_startblock,blocknr/128);
 			assert(bigblocknr>=0);
-			ret = STORAGE_get_big_block(hf,bigblocknr,block);
+			ret = STORAGE_get_big_block(str,bigblocknr,block);
 			assert(ret);
 			lastblocknr = blocknr;
 		}
@@ -544,18 +632,19 @@
  * STORAGE_get_pps_entry [INTERNAL]
  */
 static int
-STORAGE_get_pps_entry(HANDLE hf,int n,struct storage_pps_entry *pstde) {
+STORAGE_get_pps_entry(stream_access16*str,int n,struct storage_pps_entry *pstde) {
 	int	blocknr;
 	BYTE	block[BIGSIZE];
 	struct storage_pps_entry *stde = (struct storage_pps_entry*)(((LPBYTE)block)+128*(n&3));
 	struct storage_header sth;
 	BOOL ret;
 
-	READ_HEADER;
+	TRACE("(n=%d)\n", n);
+	READ_HEADER(str);
 	/* we have 4 pps entries per big block */
-	blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4);
+	blocknr = STORAGE_get_nth_next_big_blocknr(str,sth.root_startblock,n/4);
 	assert(blocknr>=0);
-	ret = STORAGE_get_big_block(hf,blocknr,block);
+	ret = STORAGE_get_big_block(str,blocknr,block);
 	assert(ret);
 
 	*pstde=*stde;
@@ -566,22 +655,22 @@
  *		STORAGE_put_pps_entry	[Internal]
  */
 static int
-STORAGE_put_pps_entry(HANDLE hf,int n,struct storage_pps_entry *pstde) {
+STORAGE_put_pps_entry(stream_access16*str,int n,struct storage_pps_entry *pstde) {
 	int	blocknr;
 	BYTE	block[BIGSIZE];
 	struct storage_pps_entry *stde = (struct storage_pps_entry*)(((LPBYTE)block)+128*(n&3));
 	struct storage_header sth;
 	BOOL ret;
 
-	READ_HEADER;
-
+	TRACE("(n=%d)\n", n);
+	READ_HEADER(str);
 	/* we have 4 pps entries per big block */
-	blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4);
+	blocknr = STORAGE_get_nth_next_big_blocknr(str,sth.root_startblock,n/4);
 	assert(blocknr>=0);
-	ret = STORAGE_get_big_block(hf,blocknr,block);
+	ret = STORAGE_get_big_block(str,blocknr,block);
 	assert(ret);
 	*stde=*pstde;
-	ret = STORAGE_put_big_block(hf,blocknr,block);
+	ret = STORAGE_put_big_block(str,blocknr,block);
 	assert(ret);
 	return 1;
 }
@@ -590,24 +679,25 @@
  *		STORAGE_look_for_named_pps	[Internal]
  */
 static int
-STORAGE_look_for_named_pps(HANDLE hf,int n,LPOLESTR name) {
+STORAGE_look_for_named_pps(stream_access16*str,int n,LPOLESTR name) {
 	struct storage_pps_entry	stde;
 	int				ret;
 
+	TRACE("(n=%d,name=%s)\n", n, debugstr_w(name));
 	if (n==-1)
 		return -1;
-	if (1!=STORAGE_get_pps_entry(hf,n,&stde))
+	if (1!=STORAGE_get_pps_entry(str,n,&stde))
 		return -1;
 
 	if (!lstrcmpW(name,stde.pps_rawname))
 		return n;
 	if (stde.pps_prev != -1) {
-		ret=STORAGE_look_for_named_pps(hf,stde.pps_prev,name);
+		ret=STORAGE_look_for_named_pps(str,stde.pps_prev,name);
 		if (ret!=-1)
 			return ret;
 	}
 	if (stde.pps_next != -1) {
-		ret=STORAGE_look_for_named_pps(hf,stde.pps_next,name);
+		ret=STORAGE_look_for_named_pps(str,stde.pps_next,name);
 		if (ret!=-1)
 			return ret;
 	}
@@ -651,14 +741,15 @@
  * STORAGE_init_storage [INTERNAL]
  */
 static BOOL
-STORAGE_init_storage(HANDLE hf) {
+STORAGE_init_storage(stream_access16 *str) {
 	BYTE	block[BIGSIZE];
 	LPDWORD	bbs;
 	struct storage_header *sth;
 	struct storage_pps_entry *stde;
         DWORD result;
 
-        SetFilePointer( hf, 0, NULL, SEEK_SET );
+	if (str->hf)
+	    SetFilePointer( str->hf, 0, NULL, SEEK_SET );
 	/* block -1 is the storage header */
 	sth = (struct storage_header*)block;
 	memcpy(sth->magic,STORAGE_magic,8);
@@ -670,13 +761,21 @@
 	sth->sbd_startblock	= 0xffffffff;
 	memset(sth->bbd_list,0xff,sizeof(sth->bbd_list));
 	sth->bbd_list[0]	= 0;
-        if (!WriteFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE) return FALSE;
+	if (str->hf) {
+	    if (!WriteFile( str->hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE) return FALSE;
+	} else {
+	    if (!_ilockbytes16_writeat(str->lockbytes, 0, BIGSIZE, block)) return FALSE;
+	}
 	/* block 0 is the big block directory */
 	bbs=(LPDWORD)block;
 	memset(block,0xff,sizeof(block)); /* mark all blocks as free */
 	bbs[0]=STORAGE_CHAINENTRY_ENDOFCHAIN; /* for this block */
 	bbs[1]=STORAGE_CHAINENTRY_ENDOFCHAIN; /* for directory entry */
-        if (!WriteFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE) return FALSE;
+	if (str->hf) {
+	    if (!WriteFile( str->hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE) return FALSE;
+	} else {
+	    if (!_ilockbytes16_writeat(str->lockbytes, BIGSIZE, BIGSIZE, block)) return FALSE;
+	}
 	/* block 1 is the root directory entry */
 	memset(block,0x00,sizeof(block));
 	stde = (struct storage_pps_entry*)block;
@@ -689,33 +788,37 @@
 	stde->pps_prev		= -1;
 	stde->pps_sb		= 0xffffffff;
 	stde->pps_size		= 0;
-        return (WriteFile( hf, block, BIGSIZE, &result, NULL ) && result == BIGSIZE);
+	if (str->hf) {
+	    return (WriteFile( str->hf, block, BIGSIZE, &result, NULL ) && result == BIGSIZE);
+	} else {
+	    return _ilockbytes16_writeat(str->lockbytes, BIGSIZE, BIGSIZE, block);
+	}
 }
 
 /******************************************************************************
  *		STORAGE_set_big_chain	[Internal]
  */
 static BOOL
-STORAGE_set_big_chain(HANDLE hf,int blocknr,INT type) {
+STORAGE_set_big_chain(stream_access16*str,int blocknr,INT type) {
 	BYTE	block[BIGSIZE];
 	LPINT	bbd = (LPINT)block;
 	int	nextblocknr,bigblocknr;
 	struct storage_header sth;
 	BOOL ret;
 
-	READ_HEADER;
+	READ_HEADER(str);
 	assert(blocknr!=type);
 	while (blocknr>=0) {
 		bigblocknr = sth.bbd_list[blocknr/128];
 		assert(bigblocknr>=0);
-		ret = STORAGE_get_big_block(hf,bigblocknr,block);
+		ret = STORAGE_get_big_block(str,bigblocknr,block);
 		assert(ret);
 
 		nextblocknr = bbd[blocknr&(128-1)];
 		bbd[blocknr&(128-1)] = type;
 		if (type>=0)
 			return TRUE;
-		ret = STORAGE_put_big_block(hf,bigblocknr,block);
+		ret = STORAGE_put_big_block(str,bigblocknr,block);
 		assert(ret);
 		type = STORAGE_CHAINENTRY_FREE;
 		blocknr = nextblocknr;
@@ -727,29 +830,29 @@
  * STORAGE_set_small_chain [Internal]
  */
 static BOOL
-STORAGE_set_small_chain(HANDLE hf,int blocknr,INT type) {
+STORAGE_set_small_chain(stream_access16*str,int blocknr,INT type) {
 	BYTE	block[BIGSIZE];
 	LPINT	sbd = (LPINT)block;
 	int	lastblocknr,nextsmallblocknr,bigblocknr;
 	struct storage_header sth;
 	BOOL ret;
 
-	READ_HEADER;
+	READ_HEADER(str);
 
 	assert(blocknr!=type);
 	lastblocknr=-129;bigblocknr=-2;
 	while (blocknr>=0) {
 		/* cache block ... */
 		if (lastblocknr/128!=blocknr/128) {
-			bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
+			bigblocknr = STORAGE_get_nth_next_big_blocknr(str,sth.sbd_startblock,blocknr/128);
 			assert(bigblocknr>=0);
-			ret = STORAGE_get_big_block(hf,bigblocknr,block);
+			ret = STORAGE_get_big_block(str,bigblocknr,block);
 			assert(ret);
 		}
 		lastblocknr = blocknr;
 		nextsmallblocknr = sbd[blocknr&(128-1)];
 		sbd[blocknr&(128-1)] = type;
-		ret = STORAGE_put_big_block(hf,bigblocknr,block);
+		ret = STORAGE_put_big_block(str,bigblocknr,block);
 		assert(ret);
 		if (type>=0)
 			return TRUE;
@@ -763,7 +866,7 @@
  *		STORAGE_get_free_big_blocknr	[Internal]
  */
 static int
-STORAGE_get_free_big_blocknr(HANDLE hf) {
+STORAGE_get_free_big_blocknr(stream_access16 *str) {
 	BYTE	block[BIGSIZE];
 	LPINT	sbd = (LPINT)block;
 	int	lastbigblocknr,i,bigblocknr;
@@ -771,21 +874,21 @@
 	struct storage_header sth;
 	BOOL ret;
 
-	READ_HEADER;
+	READ_HEADER(str);
 	curblock	= 0;
 	lastbigblocknr	= -1;
 	bigblocknr	= sth.bbd_list[curblock];
 	while (curblock<sth.num_of_bbd_blocks) {
 		assert(bigblocknr>=0);
-		ret = STORAGE_get_big_block(hf,bigblocknr,block);
+		ret = STORAGE_get_big_block(str,bigblocknr,block);
 		assert(ret);
 		for (i=0;i<128;i++)
 			if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
 				sbd[i] = STORAGE_CHAINENTRY_ENDOFCHAIN;
-				ret = STORAGE_put_big_block(hf,bigblocknr,block);
+				ret = STORAGE_put_big_block(str,bigblocknr,block);
 				assert(ret);
 				memset(block,0x42,sizeof(block));
-				ret = STORAGE_put_big_block(hf,i+curblock*128,block);
+				ret = STORAGE_put_big_block(str,i+curblock*128,block);
 				assert(ret);
 				return i+curblock*128;
 			}
@@ -800,30 +903,30 @@
 	memset(block,0xff,sizeof(block));
 	/* mark the block allocated and returned by this function */
 	sbd[1] = STORAGE_CHAINENTRY_ENDOFCHAIN;
-	ret = STORAGE_put_big_block(hf,bigblocknr,block);
+	ret = STORAGE_put_big_block(str,bigblocknr,block);
 	assert(ret);
 
 	/* if we had a bbd block already (mostlikely) we need
 	 * to link the new one into the chain
 	 */
 	if (lastbigblocknr!=-1) {
-		ret = STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr);
+		ret = STORAGE_set_big_chain(str,lastbigblocknr,bigblocknr);
 		assert(ret);
 	}
 	sth.bbd_list[curblock]=bigblocknr;
 	sth.num_of_bbd_blocks++;
 	assert(sth.num_of_bbd_blocks==curblock+1);
-	ret = STORAGE_put_big_block(hf,-1,(LPBYTE)&sth);
+	ret = STORAGE_put_big_block(str,-1,(LPBYTE)&sth);
 	assert(ret);
 
 	/* Set the end of the chain for the bigblockdepots */
-	ret = STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN);
+	ret = STORAGE_set_big_chain(str,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN);
 	assert(ret);
 	/* add 1, for the first entry is used for the additional big block
 	 * depot. (means we already used bigblocknr) */
 	memset(block,0x42,sizeof(block));
 	/* allocate this block (filled with 0x42) */
-	ret = STORAGE_put_big_block(hf,bigblocknr+1,block);
+	ret = STORAGE_put_big_block(str,bigblocknr+1,block);
 	assert(ret);
 	return bigblocknr+1;
 }
@@ -833,20 +936,20 @@
  *		STORAGE_get_free_small_blocknr	[Internal]
  */
 static int
-STORAGE_get_free_small_blocknr(HANDLE hf) {
+STORAGE_get_free_small_blocknr(stream_access16 *str) {
 	BYTE	block[BIGSIZE];
 	LPINT	sbd = (LPINT)block;
 	int	lastbigblocknr,newblocknr,i,curblock,bigblocknr;
 	struct storage_pps_entry	root;
 	struct storage_header sth;
 
-	READ_HEADER;
+	READ_HEADER(str);
 	bigblocknr	= sth.sbd_startblock;
 	curblock	= 0;
 	lastbigblocknr	= -1;
 	newblocknr	= -1;
 	while (bigblocknr>=0) {
-		if (!STORAGE_get_big_block(hf,bigblocknr,block))
+		if (!STORAGE_get_big_block(str,bigblocknr,block))
 			return -1;
 		for (i=0;i<128;i++)
 			if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
@@ -857,56 +960,56 @@
 		if (i!=128)
 			break;
 		lastbigblocknr = bigblocknr;
-		bigblocknr = STORAGE_get_next_big_blocknr(hf,bigblocknr);
+		bigblocknr = STORAGE_get_next_big_blocknr(str,bigblocknr);
 		curblock++;
 	}
 	if (newblocknr==-1) {
-		bigblocknr = STORAGE_get_free_big_blocknr(hf);
+		bigblocknr = STORAGE_get_free_big_blocknr(str);
 		if (bigblocknr<0)
 			return -1;
-		READ_HEADER;
+		READ_HEADER(str);
 		memset(block,0xff,sizeof(block));
 		sbd[0]=STORAGE_CHAINENTRY_ENDOFCHAIN;
-		if (!STORAGE_put_big_block(hf,bigblocknr,block))
+		if (!STORAGE_put_big_block(str,bigblocknr,block))
 			return -1;
 		if (lastbigblocknr==-1) {
 			sth.sbd_startblock = bigblocknr;
-			if (!STORAGE_put_big_block(hf,-1,(LPBYTE)&sth)) /* need to write it */
+			if (!STORAGE_put_big_block(str,-1,(LPBYTE)&sth)) /* need to write it */
 				return -1;
 		} else {
-			if (!STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr))
+			if (!STORAGE_set_big_chain(str,lastbigblocknr,bigblocknr))
 				return -1;
 		}
-		if (!STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+		if (!STORAGE_set_big_chain(str,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 			return -1;
 		newblocknr = curblock*128;
 	}
 	/* allocate enough big blocks for storing the allocated small block */
-	if (!STORAGE_get_root_pps_entry(hf,&root))
+	if (!STORAGE_get_root_pps_entry(str,&root))
 		return -1;
 	if (root.pps_sb==-1)
 		lastbigblocknr	= -1;
 	else
-		lastbigblocknr	= STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,(root.pps_size-1)/BIGSIZE);
+		lastbigblocknr	= STORAGE_get_nth_next_big_blocknr(str,root.pps_sb,(root.pps_size-1)/BIGSIZE);
 	while (root.pps_size < (newblocknr*SMALLSIZE+SMALLSIZE-1)) {
 		/* we need to allocate more stuff */
-		bigblocknr = STORAGE_get_free_big_blocknr(hf);
+		bigblocknr = STORAGE_get_free_big_blocknr(str);
 		if (bigblocknr<0)
 			return -1;
-		READ_HEADER;
+		READ_HEADER(str);
 		if (root.pps_sb==-1) {
 			root.pps_sb	 = bigblocknr;
 			root.pps_size	+= BIGSIZE;
 		} else {
-			if (!STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr))
+			if (!STORAGE_set_big_chain(str,lastbigblocknr,bigblocknr))
 				return -1;
 			root.pps_size	+= BIGSIZE;
 		}
 		lastbigblocknr = bigblocknr;
 	}
-	if (!STORAGE_set_big_chain(hf,lastbigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+	if (!STORAGE_set_big_chain(str,lastbigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 		return -1;
-	if (!STORAGE_put_pps_entry(hf,0,&root))
+	if (!STORAGE_put_pps_entry(str,0,&root))
 		return -1;
 	return newblocknr;
 }
@@ -915,38 +1018,38 @@
  *		STORAGE_get_free_pps_entry	[Internal]
  */
 static int
-STORAGE_get_free_pps_entry(HANDLE hf) {
+STORAGE_get_free_pps_entry(stream_access16*str) {
 	int	blocknr, i, curblock, lastblocknr=-1;
 	BYTE	block[BIGSIZE];
 	struct storage_pps_entry *stde = (struct storage_pps_entry*)block;
 	struct storage_header sth;
 
-	READ_HEADER;
+	READ_HEADER(str);
 	blocknr = sth.root_startblock;
 	assert(blocknr>=0);
 	curblock=0;
 	while (blocknr>=0) {
-		if (!STORAGE_get_big_block(hf,blocknr,block))
+		if (!STORAGE_get_big_block(str,blocknr,block))
 			return -1;
 		for (i=0;i<4;i++)
 			if (stde[i].pps_sizeofname==0) /* free */
 				return curblock*4+i;
 		lastblocknr = blocknr;
-		blocknr = STORAGE_get_next_big_blocknr(hf,blocknr);
+		blocknr = STORAGE_get_next_big_blocknr(str,blocknr);
 		curblock++;
 	}
 	assert(blocknr==STORAGE_CHAINENTRY_ENDOFCHAIN);
-	blocknr = STORAGE_get_free_big_blocknr(hf);
+	blocknr = STORAGE_get_free_big_blocknr(str);
 	/* sth invalidated */
 	if (blocknr<0)
 		return -1;
 
-	if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
+	if (!STORAGE_set_big_chain(str,lastblocknr,blocknr))
 		return -1;
-	if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+	if (!STORAGE_set_big_chain(str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 		return -1;
 	memset(block,0,sizeof(block));
-	STORAGE_put_big_block(hf,blocknr,block);
+	STORAGE_put_big_block(str,blocknr,block);
 	return curblock*4;
 }
 
@@ -961,8 +1064,8 @@
         SEGPTR                          thisptr; /* pointer to this struct as segmented */
         struct storage_pps_entry        stde;
         int                             ppsent;
-        HANDLE                         hf;
         ULARGE_INTEGER                  offset;
+	stream_access16			str;
 } IStream16Impl;
 
 /******************************************************************************
@@ -989,20 +1092,82 @@
 	return InterlockedIncrement(&This->ref);
 }
 
+static void
+_ilockbytes16_addref(SEGPTR lockbytes) {
+    DWORD args[1];
+    HRESULT hres;
+    
+    args[0] = (DWORD)lockbytes;	/* iface */
+    if (!K32WOWCallback16Ex(
+	(DWORD)((const ILockBytes16Vtbl*)MapSL(
+		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
+	)->AddRef,
+	WCB16_PASCAL,
+	1*sizeof(DWORD),
+	(LPVOID)args,
+	(LPDWORD)&hres
+    ))
+	ERR("CallTo16 ILockBytes16::AddRef() failed, hres %lx\n",hres);
+}
+
+static void
+_ilockbytes16_release(SEGPTR lockbytes) {
+    DWORD args[1];
+    HRESULT hres;
+    
+    args[0] = (DWORD)lockbytes;	/* iface */
+    if (!K32WOWCallback16Ex(
+	(DWORD)((const ILockBytes16Vtbl*)MapSL(
+		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
+	)->Release,
+	WCB16_PASCAL,
+	1*sizeof(DWORD),
+	(LPVOID)args,
+	(LPDWORD)&hres
+    ))
+	ERR("CallTo16 ILockBytes16::Release() failed, hres %lx\n",hres);
+}
+
+static void
+_ilockbytes16_flush(SEGPTR lockbytes) {
+    DWORD args[1];
+    HRESULT hres;
+    
+    args[0] = (DWORD)lockbytes;	/* iface */
+    if (!K32WOWCallback16Ex(
+	(DWORD)((const ILockBytes16Vtbl*)MapSL(
+		    (SEGPTR)((LPLOCKBYTES16)MapSL(lockbytes))->lpVtbl)
+	)->Flush,
+	WCB16_PASCAL,
+	1*sizeof(DWORD),
+	(LPVOID)args,
+	(LPDWORD)&hres
+    ))
+	ERR("CallTo16 ILockBytes16::Flush() failed, hres %lx\n",hres);
+}
+
 /******************************************************************************
  * IStream16_Release [STORAGE.520]
  */
 ULONG IStream16_fnRelease(IStream16* iface) {
 	IStream16Impl *This = (IStream16Impl *)iface;
         ULONG ref;
-	FlushFileBuffers(This->hf);
+
+	if (This->str.hf)
+	    FlushFileBuffers(This->str.hf);
+	else
+	    _ilockbytes16_flush(This->str.lockbytes);
         ref = InterlockedDecrement(&This->ref);
-	if (!ref) {
-		CloseHandle(This->hf);
-                UnMapLS( This->thisptr );
-		HeapFree( GetProcessHeap(), 0, This );
-	}
-	return ref;
+	if (ref)
+	    return ref;
+
+	if (This->str.hf)
+	    CloseHandle(This->str.hf);
+	else
+	    _ilockbytes16_release(This->str.lockbytes);
+        UnMapLS( This->thisptr );
+	HeapFree( GetProcessHeap(), 0, This );
+	return 0;
 }
 
 /******************************************************************************
@@ -1072,11 +1237,11 @@
 		cb=This->stde.pps_size-This->offset.u.LowPart;
 	if (This->stde.pps_size < 0x1000) {
 		/* use small block reader */
-		blocknr = STORAGE_get_nth_next_small_blocknr(This->hf,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
+		blocknr = STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
 		while (cb) {
 			unsigned int cc;
 
-			if (!STORAGE_get_small_block(This->hf,blocknr,block)) {
+			if (!STORAGE_get_small_block(&This->str,blocknr,block)) {
 			   WARN("small block read failed!!!\n");
 				return E_FAIL;
 			}
@@ -1088,15 +1253,15 @@
 			pbv+=cc;
 			*bytesread+=cc;
 			cb-=cc;
-			blocknr = STORAGE_get_next_small_blocknr(This->hf,blocknr);
+			blocknr = STORAGE_get_next_small_blocknr(&This->str,blocknr);
 		}
 	} else {
 		/* use big block reader */
-		blocknr = STORAGE_get_nth_next_big_blocknr(This->hf,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
+		blocknr = STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
 		while (cb) {
 			unsigned int cc;
 
-			if (!STORAGE_get_big_block(This->hf,blocknr,block)) {
+			if (!STORAGE_get_big_block(&This->str,blocknr,block)) {
 				WARN("big block read failed!!!\n");
 				return E_FAIL;
 			}
@@ -1108,7 +1273,7 @@
 			pbv+=cc;
 			*bytesread+=cc;
 			cb-=cc;
-			blocknr=STORAGE_get_next_big_blocknr(This->hf,blocknr);
+			blocknr=STORAGE_get_next_big_blocknr(&This->str,blocknr);
 		}
 	}
 	return S_OK;
@@ -1124,7 +1289,6 @@
 	BYTE	block[BIGSIZE];
 	ULONG	*byteswritten=pcbWrite,xxwritten;
 	int	oldsize,newsize,i,curoffset=0,lastblocknr,blocknr,cc;
-	HANDLE	hf = This->hf;
 	const BYTE*     pbv = (const BYTE*)pv;
 
 	if (!pcbWrite) byteswritten=&xxwritten;
@@ -1137,20 +1301,20 @@
 	if (newsize < oldsize) {
 		if (oldsize < 0x1000) {
 			/* only small blocks */
-			blocknr=STORAGE_get_nth_next_small_blocknr(hf,This->stde.pps_sb,newsize/SMALLSIZE);
+			blocknr=STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,newsize/SMALLSIZE);
 
 			assert(blocknr>=0);
 
 			/* will set the rest of the chain to 'free' */
-			if (!STORAGE_set_small_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+			if (!STORAGE_set_small_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 				return E_FAIL;
 		} else {
 			if (newsize >= 0x1000) {
-				blocknr=STORAGE_get_nth_next_big_blocknr(hf,This->stde.pps_sb,newsize/BIGSIZE);
+				blocknr=STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,newsize/BIGSIZE);
 				assert(blocknr>=0);
 
 				/* will set the rest of the chain to 'free' */
-				if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+				if (!STORAGE_set_big_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 					return E_FAIL;
 			} else {
 				/* Migrate large blocks to small blocks
@@ -1163,35 +1327,35 @@
 				blocknr = This->stde.pps_sb;
 				curdata = data;
 				while (cc>0) {
-					if (!STORAGE_get_big_block(hf,blocknr,curdata)) {
+					if (!STORAGE_get_big_block(&This->str,blocknr,curdata)) {
 						HeapFree(GetProcessHeap(),0,data);
 						return E_FAIL;
 					}
 					curdata	+= BIGSIZE;
 					cc	-= BIGSIZE;
-					blocknr	 = STORAGE_get_next_big_blocknr(hf,blocknr);
+					blocknr	 = STORAGE_get_next_big_blocknr(&This->str,blocknr);
 				}
 				/* frees complete chain for this stream */
-				if (!STORAGE_set_big_chain(hf,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
+				if (!STORAGE_set_big_chain(&This->str,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
 					goto err;
 				curdata	= data;
-				blocknr = This->stde.pps_sb = STORAGE_get_free_small_blocknr(hf);
+				blocknr = This->stde.pps_sb = STORAGE_get_free_small_blocknr(&This->str);
 				if (blocknr<0)
 					goto err;
 				cc	= newsize;
 				while (cc>0) {
-					if (!STORAGE_put_small_block(hf,blocknr,curdata))
+					if (!STORAGE_put_small_block(&This->str,blocknr,curdata))
 						goto err;
 					cc	-= SMALLSIZE;
 					if (cc<=0) {
-						if (!STORAGE_set_small_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+						if (!STORAGE_set_small_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 							goto err;
 						break;
 					} else {
-						int newblocknr = STORAGE_get_free_small_blocknr(hf);
+						int newblocknr = STORAGE_get_free_small_blocknr(&This->str);
 						if (newblocknr<0)
 							goto err;
-						if (!STORAGE_set_small_chain(hf,blocknr,newblocknr))
+						if (!STORAGE_set_small_chain(&This->str,blocknr,newblocknr))
 							goto err;
 						blocknr = newblocknr;
 					}
@@ -1210,46 +1374,46 @@
 	if (newsize > oldsize) {
 		if (oldsize >= 0x1000) {
 			/* should return the block right before the 'endofchain' */
-			blocknr = STORAGE_get_nth_next_big_blocknr(hf,This->stde.pps_sb,This->stde.pps_size/BIGSIZE);
+			blocknr = STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,This->stde.pps_size/BIGSIZE);
 			assert(blocknr>=0);
 			lastblocknr	= blocknr;
 			for (i=oldsize/BIGSIZE;i<newsize/BIGSIZE;i++) {
-				blocknr = STORAGE_get_free_big_blocknr(hf);
+				blocknr = STORAGE_get_free_big_blocknr(&This->str);
 				if (blocknr<0)
 					return E_FAIL;
-				if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
+				if (!STORAGE_set_big_chain(&This->str,lastblocknr,blocknr))
 					return E_FAIL;
 				lastblocknr = blocknr;
 			}
-			if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+			if (!STORAGE_set_big_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 				return E_FAIL;
 		} else {
 			if (newsize < 0x1000) {
 				/* find startblock */
 				if (!oldsize)
-					This->stde.pps_sb = blocknr = STORAGE_get_free_small_blocknr(hf);
+					This->stde.pps_sb = blocknr = STORAGE_get_free_small_blocknr(&This->str);
 				else
-					blocknr = STORAGE_get_nth_next_small_blocknr(hf,This->stde.pps_sb,This->stde.pps_size/SMALLSIZE);
+					blocknr = STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,This->stde.pps_size/SMALLSIZE);
 				if (blocknr<0)
 					return E_FAIL;
 
 				/* allocate required new small blocks */
 				lastblocknr = blocknr;
 				for (i=oldsize/SMALLSIZE;i<newsize/SMALLSIZE;i++) {
-					blocknr = STORAGE_get_free_small_blocknr(hf);
+					blocknr = STORAGE_get_free_small_blocknr(&This->str);
 					if (blocknr<0)
 						return E_FAIL;
-					if (!STORAGE_set_small_chain(hf,lastblocknr,blocknr))
+					if (!STORAGE_set_small_chain(&This->str,lastblocknr,blocknr))
 						return E_FAIL;
 					lastblocknr = blocknr;
 				}
 				/* and terminate the chain */
-				if (!STORAGE_set_small_chain(hf,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+				if (!STORAGE_set_small_chain(&This->str,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 					return E_FAIL;
 			} else {
 				if (!oldsize) {
 					/* no single block allocated yet */
-					blocknr=STORAGE_get_free_big_blocknr(hf);
+					blocknr=STORAGE_get_free_big_blocknr(&This->str);
 					if (blocknr<0)
 						return E_FAIL;
 					This->stde.pps_sb = blocknr;
@@ -1263,34 +1427,34 @@
 					curdata = data;
 					/* slurp in */
 					while (cc>0) {
-						if (!STORAGE_get_small_block(hf,blocknr,curdata))
+						if (!STORAGE_get_small_block(&This->str,blocknr,curdata))
 							goto err2;
 						curdata	+= SMALLSIZE;
 						cc	-= SMALLSIZE;
-						blocknr	 = STORAGE_get_next_small_blocknr(hf,blocknr);
+						blocknr	 = STORAGE_get_next_small_blocknr(&This->str,blocknr);
 					}
 					/* free small block chain */
-					if (!STORAGE_set_small_chain(hf,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
+					if (!STORAGE_set_small_chain(&This->str,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
 						goto err2;
 					curdata	= data;
-					blocknr = This->stde.pps_sb = STORAGE_get_free_big_blocknr(hf);
+					blocknr = This->stde.pps_sb = STORAGE_get_free_big_blocknr(&This->str);
 					if (blocknr<0)
 						goto err2;
 					/* put the data into the big blocks */
 					cc	= This->stde.pps_size;
 					while (cc>0) {
-						if (!STORAGE_put_big_block(hf,blocknr,curdata))
+						if (!STORAGE_put_big_block(&This->str,blocknr,curdata))
 							goto err2;
 						cc	-= BIGSIZE;
 						if (cc<=0) {
-							if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+							if (!STORAGE_set_big_chain(&This->str,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 								goto err2;
 							break;
 						} else {
-							int newblocknr = STORAGE_get_free_big_blocknr(hf);
+							int newblocknr = STORAGE_get_free_big_blocknr(&This->str);
 							if (newblocknr<0)
 								goto err2;
-							if (!STORAGE_set_big_chain(hf,blocknr,newblocknr))
+							if (!STORAGE_set_big_chain(&This->str,blocknr,newblocknr))
 								goto err2;
 							blocknr = newblocknr;
 						}
@@ -1305,15 +1469,15 @@
 				/* generate big blocks to fit the new data */
 				lastblocknr	= blocknr;
 				for (i=oldsize/BIGSIZE;i<newsize/BIGSIZE;i++) {
-					blocknr = STORAGE_get_free_big_blocknr(hf);
+					blocknr = STORAGE_get_free_big_blocknr(&This->str);
 					if (blocknr<0)
 						return E_FAIL;
-					if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
+					if (!STORAGE_set_big_chain(&This->str,lastblocknr,blocknr))
 						return E_FAIL;
 					lastblocknr = blocknr;
 				}
 				/* terminate chain */
-				if (!STORAGE_set_big_chain(hf,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
+				if (!STORAGE_set_big_chain(&This->str,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
 					return E_FAIL;
 			}
 		}
@@ -1323,12 +1487,12 @@
 	/* There are just some cases where we didn't modify it, we write it out
 	 * everytime
 	 */
-	if (!STORAGE_put_pps_entry(hf,This->ppsent,&(This->stde)))
+	if (!STORAGE_put_pps_entry(&This->str,This->ppsent,&(This->stde)))
 		return E_FAIL;
 
 	/* finally the write pass */
 	if (This->stde.pps_size < 0x1000) {
-		blocknr = STORAGE_get_nth_next_small_blocknr(hf,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
+		blocknr = STORAGE_get_nth_next_small_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
 		assert(blocknr>=0);
 		while (cb>0) {
 			/* we ensured that it is allocated above */
@@ -1336,7 +1500,7 @@
 			/* Read old block everytime, since we can have
 			 * overlapping data at START and END of the write
 			 */
-			if (!STORAGE_get_small_block(hf,blocknr,block))
+			if (!STORAGE_get_small_block(&This->str,blocknr,block))
 				return E_FAIL;
 
 			cc = SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1));
@@ -1346,17 +1510,17 @@
 				pbv+curoffset,
 				cc
 			);
-			if (!STORAGE_put_small_block(hf,blocknr,block))
+			if (!STORAGE_put_small_block(&This->str,blocknr,block))
 				return E_FAIL;
 			cb			-= cc;
 			curoffset		+= cc;
 			pbv			+= cc;
 			This->offset.u.LowPart	+= cc;
 			*byteswritten		+= cc;
-			blocknr = STORAGE_get_next_small_blocknr(hf,blocknr);
+			blocknr = STORAGE_get_next_small_blocknr(&This->str,blocknr);
 		}
 	} else {
-		blocknr = STORAGE_get_nth_next_big_blocknr(hf,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
+		blocknr = STORAGE_get_nth_next_big_blocknr(&This->str,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
 		assert(blocknr>=0);
 		while (cb>0) {
 			/* we ensured that it is allocated above, so it better is */
@@ -1364,7 +1528,7 @@
 			/* read old block everytime, since we can have
 			 * overlapping data at START and END of the write
 			 */
-			if (!STORAGE_get_big_block(hf,blocknr,block))
+			if (!STORAGE_get_big_block(&This->str,blocknr,block))
 				return E_FAIL;
 
 			cc = BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1));
@@ -1374,14 +1538,14 @@
 				pbv+curoffset,
 				cc
 			);
-			if (!STORAGE_put_big_block(hf,blocknr,block))
+			if (!STORAGE_put_big_block(&This->str,blocknr,block))
 				return E_FAIL;
 			cb			-= cc;
 			curoffset		+= cc;
 			pbv			+= cc;
 			This->offset.u.LowPart	+= cc;
 			*byteswritten		+= cc;
-			blocknr = STORAGE_get_next_big_blocknr(hf,blocknr);
+			blocknr = STORAGE_get_next_big_blocknr(&This->str,blocknr);
 		}
 	}
 	return S_OK;
@@ -1440,6 +1604,8 @@
 	lpst->lpVtbl	= segstrvt16;
 	lpst->ref	= 1;
 	lpst->thisptr	= MapLS( lpst );
+	lpst->str.hf	= NULL;
+	lpst->str.lockbytes	= 0;
 	*str = (void*)lpst->thisptr;
 }
 
@@ -1454,7 +1620,7 @@
         /* IStream32 fields */
         struct storage_pps_entry        stde;
         int                             ppsent;
-        HANDLE                         hf;
+        HANDLE                          hf;
         ULARGE_INTEGER                  offset;
 } IStream32Impl;
 
@@ -1498,20 +1664,6 @@
 	return ref;
 }
 
-/* --- IStorage16 implementation */
-
-typedef struct
-{
-        /* IUnknown fields */
-        const IStorage16Vtbl           *lpVtbl;
-        LONG                            ref;
-        /* IStorage16 fields */
-        SEGPTR                          thisptr; /* pointer to this struct as segmented */
-        struct storage_pps_entry        stde;
-        int                             ppsent;
-        HANDLE                         hf;
-} IStorage16Impl;
-
 /******************************************************************************
  *		IStorage16_QueryInterface	[STORAGE.500]
  */
@@ -1616,12 +1768,10 @@
 	int		ppsent,x;
 	struct storage_pps_entry	stde;
 	struct storage_header sth;
-	HANDLE		hf=This->hf;
 	BOOL ret;
 	int	 nPPSEntries;
 
-	READ_HEADER;
-
+	READ_HEADER(&This->str);
 	TRACE("(%p)->(%s,0x%08lx,0x%08lx,0x%08lx,%p)\n",
 		This,pwcsName,grfMode,dwStgFormat,reserved2,ppstg
 	);
@@ -1629,9 +1779,15 @@
 		FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
 	_create_istorage16(ppstg);
 	lpstg = MapSL((SEGPTR)*ppstg);
-	lpstg->hf		= This->hf;
+	if (This->str.hf) {
+	    DuplicateHandle( GetCurrentProcess(), This->str.hf, GetCurrentProcess(),
+			     &lpstg->str.hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	} else {
+	    lpstg->str.lockbytes = This->str.lockbytes;
+	    _ilockbytes16_addref(This->str.lockbytes);
+	}
 
-	ppsent=STORAGE_get_free_pps_entry(lpstg->hf);
+	ppsent=STORAGE_get_free_pps_entry(&lpstg->str);
 	if (ppsent<0)
 		return E_FAIL;
 	stde=This->stde;
@@ -1641,18 +1797,18 @@
 	} else {
 		FIXME(" use prev chain too ?\n");
 		x=stde.pps_dir;
-		if (1!=STORAGE_get_pps_entry(lpstg->hf,x,&stde))
+		if (1!=STORAGE_get_pps_entry(&lpstg->str,x,&stde))
 			return E_FAIL;
 		while (stde.pps_next!=-1) {
 			x=stde.pps_next;
-			if (1!=STORAGE_get_pps_entry(lpstg->hf,x,&stde))
+			if (1!=STORAGE_get_pps_entry(&lpstg->str,x,&stde))
 				return E_FAIL;
 		}
 		stde.pps_next = ppsent;
 	}
-	ret = STORAGE_put_pps_entry(lpstg->hf,x,&stde);
+	ret = STORAGE_put_pps_entry(&lpstg->str,x,&stde);
 	assert(ret);
-	nPPSEntries = STORAGE_get_pps_entry(lpstg->hf,ppsent,&(lpstg->stde));
+	nPPSEntries = STORAGE_get_pps_entry(&lpstg->str,ppsent,&(lpstg->stde));
 	assert(nPPSEntries == 1);
         MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, lpstg->stde.pps_rawname,
                              sizeof(lpstg->stde.pps_rawname)/sizeof(WCHAR));
@@ -1665,7 +1821,7 @@
 	lpstg->stde.pps_type	=  1;
 	lpstg->ppsent		= ppsent;
 	/* FIXME: timestamps? */
-	if (!STORAGE_put_pps_entry(lpstg->hf,ppsent,&(lpstg->stde)))
+	if (!STORAGE_put_pps_entry(&lpstg->str,ppsent,&(lpstg->stde)))
 		return E_FAIL;
 	return S_OK;
 }
@@ -1690,12 +1846,17 @@
 		FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
 	_create_istream16(ppstm);
 	lpstr = MapSL((SEGPTR)*ppstm);
-        DuplicateHandle( GetCurrentProcess(), This->hf, GetCurrentProcess(),
-                         &lpstr->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	if (This->str.hf) {
+	    DuplicateHandle( GetCurrentProcess(), This->str.hf, GetCurrentProcess(),
+			     &lpstr->str.hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	} else {
+	    lpstr->str.lockbytes = This->str.lockbytes;
+	    _ilockbytes16_addref(This->str.lockbytes);
+	}
 	lpstr->offset.u.LowPart	= 0;
-	lpstr->offset.u.HighPart	= 0;
+	lpstr->offset.u.HighPart= 0;
 
-	ppsent=STORAGE_get_free_pps_entry(lpstr->hf);
+	ppsent=STORAGE_get_free_pps_entry(&lpstr->str);
 	if (ppsent<0)
 		return E_FAIL;
 	stde=This->stde;
@@ -1704,13 +1865,13 @@
 	else
 		while (stde.pps_next!=-1) {
 			x=stde.pps_next;
-			if (1!=STORAGE_get_pps_entry(lpstr->hf,x,&stde))
+			if (1!=STORAGE_get_pps_entry(&lpstr->str,x,&stde))
 				return E_FAIL;
 		}
 	stde.pps_next = ppsent;
-	ret = STORAGE_put_pps_entry(lpstr->hf,x,&stde);
+	ret = STORAGE_put_pps_entry(&lpstr->str,x,&stde);
 	assert(ret);
-	nPPSEntries = STORAGE_get_pps_entry(lpstr->hf,ppsent,&(lpstr->stde));
+	nPPSEntries = STORAGE_get_pps_entry(&lpstr->str,ppsent,&(lpstr->stde));
 	assert(nPPSEntries == 1);
         MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, lpstr->stde.pps_rawname,
                              sizeof(lpstr->stde.pps_rawname)/sizeof(WCHAR));
@@ -1722,8 +1883,9 @@
 	lpstr->stde.pps_size	=  0;
 	lpstr->stde.pps_type	=  2;
 	lpstr->ppsent		= ppsent;
+
 	/* FIXME: timestamps? */
-	if (!STORAGE_put_pps_entry(lpstr->hf,ppsent,&(lpstr->stde)))
+	if (!STORAGE_put_pps_entry(&lpstr->str,ppsent,&(lpstr->stde)))
 		return E_FAIL;
 	return S_OK;
 }
@@ -1739,23 +1901,28 @@
 	WCHAR		name[33];
 	int		newpps;
 
-	TRACE_(relay)("(%p)->(%s,%p,0x%08lx,%p,0x%08lx,%p)\n",
+	TRACE("(%p)->(%s,%p,0x%08lx,%p,0x%08lx,%p)\n",
 		This,pwcsName,pstgPrio,grfMode,snbExclude,reserved,ppstg
 	);
 	if (grfMode & STGM_TRANSACTED)
 		FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
 	_create_istorage16(ppstg);
 	lpstg = MapSL((SEGPTR)*ppstg);
-        DuplicateHandle( GetCurrentProcess(), This->hf, GetCurrentProcess(),
-                         &lpstg->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	if (This->str.hf) {
+	    DuplicateHandle( GetCurrentProcess(), This->str.hf, GetCurrentProcess(),
+			     &lpstg->str.hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	} else {
+	    lpstg->str.lockbytes = This->str.lockbytes;
+	    _ilockbytes16_addref(This->str.lockbytes);
+	}
         MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, name, sizeof(name)/sizeof(WCHAR));
-	newpps = STORAGE_look_for_named_pps(lpstg->hf,This->stde.pps_dir,name);
+	newpps = STORAGE_look_for_named_pps(&lpstg->str,This->stde.pps_dir,name);
 	if (newpps==-1) {
 		IStream16_fnRelease((IStream16*)lpstg);
 		return E_FAIL;
 	}
 
-	if (1!=STORAGE_get_pps_entry(lpstg->hf,newpps,&(lpstg->stde))) {
+	if (1!=STORAGE_get_pps_entry(&lpstg->str,newpps,&(lpstg->stde))) {
 		IStream16_fnRelease((IStream16*)lpstg);
 		return E_FAIL;
 	}
@@ -1774,29 +1941,34 @@
 	WCHAR		name[33];
 	int		newpps;
 
-	TRACE_(relay)("(%p)->(%s,%p,0x%08lx,0x%08lx,%p)\n",
+	TRACE("(%p)->(%s,%p,0x%08lx,0x%08lx,%p)\n",
 		This,pwcsName,reserved1,grfMode,reserved2,ppstm
 	);
 	if (grfMode & STGM_TRANSACTED)
 		FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
 	_create_istream16(ppstm);
 	lpstr = MapSL((SEGPTR)*ppstm);
-        DuplicateHandle( GetCurrentProcess(), This->hf, GetCurrentProcess(),
-                         &lpstr->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	if (This->str.hf) {
+	    DuplicateHandle( GetCurrentProcess(), This->str.hf, GetCurrentProcess(),
+			     &lpstr->str.hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
+	} else {
+	    lpstr->str.lockbytes = This->str.lockbytes;
+	    _ilockbytes16_addref(This->str.lockbytes);
+	}
         MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, name, sizeof(name)/sizeof(WCHAR));
-	newpps = STORAGE_look_for_named_pps(lpstr->hf,This->stde.pps_dir,name);
+	newpps = STORAGE_look_for_named_pps(&lpstr->str,This->stde.pps_dir,name);
 	if (newpps==-1) {
 		IStream16_fnRelease((IStream16*)lpstr);
 		return E_FAIL;
 	}
 
-	if (1!=STORAGE_get_pps_entry(lpstr->hf,newpps,&(lpstr->stde))) {
+	if (1!=STORAGE_get_pps_entry(&lpstr->str,newpps,&(lpstr->stde))) {
 		IStream16_fnRelease((IStream16*)lpstr);
 		return E_FAIL;
 	}
-	lpstr->offset.u.LowPart	= 0;
+	lpstr->offset.u.LowPart		= 0;
 	lpstr->offset.u.HighPart	= 0;
-	lpstr->ppsent		= newpps;
+	lpstr->ppsent			= newpps;
 	return S_OK;
 }
 
@@ -1858,6 +2030,8 @@
 	}
 	lpst = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpst) );
 	lpst->lpVtbl	= segstvt16;
+	lpst->str.hf	= NULL;
+	lpst->str.lockbytes	= 0;
 	lpst->ref	= 1;
 	lpst->thisptr	= MapLS(lpst);
 	*stg = (void*)lpst->thisptr;
@@ -1888,15 +2062,16 @@
 		return E_FAIL;
 	}
 	lpstg = MapSL((SEGPTR)*ppstgOpen);
-	lpstg->hf = hf;
+	lpstg->str.hf = hf;
+	lpstg->str.lockbytes = 0;
 	/* FIXME: check for existence before overwriting? */
-	if (!STORAGE_init_storage(hf)) {
+	if (!STORAGE_init_storage(&lpstg->str)) {
 		CloseHandle(hf);
 		return E_FAIL;
 	}
 	i=0;ret=0;
 	while (!ret) { /* neither 1 nor <0 */
-		ret=STORAGE_get_pps_entry(hf,i,&stde);
+		ret=STORAGE_get_pps_entry(&lpstg->str,i,&stde);
 		if ((ret==1) && (stde.pps_type==5)) {
 			lpstg->stde	= stde;
 			lpstg->ppsent	= i;
@@ -1948,11 +2123,11 @@
 		return E_FAIL;
 	}
 	lpstg = MapSL((SEGPTR)*ppstgOpen);
-	lpstg->hf = hf;
+	lpstg->str.hf = hf;
 
 	i=0;ret=0;
 	while (!ret) { /* neither 1 nor <0 */
-		ret=STORAGE_get_pps_entry(hf,i,&stde);
+		ret=STORAGE_get_pps_entry(&lpstg->str,i,&stde);
 		if ((ret==1) && (stde.pps_type==5)) {
 			lpstg->stde=stde;
 			break;
@@ -2008,24 +2183,92 @@
  *    StgOpenStorageOnILockBytes    [STORAGE.4]
  */
 HRESULT WINAPI StgOpenStorageOnILockBytes16(
-      ILockBytes16 *plkbyt,
-      IStorage16 *pstgPriority,
-      DWORD grfMode,
-      SNB16 snbExclude,
-      DWORD reserved,
-      IStorage16 **ppstgOpen)
+	SEGPTR /*ILockBytes16 **/plkbyt,
+	IStorage16 *pstgPriority,
+	DWORD grfMode,
+	SNB16 snbExclude,
+	DWORD reserved,
+	IStorage16 **ppstgOpen)
 {
-  IStorage16Impl*	lpstg;
+	IStorage16Impl*	lpstg;
+	int i,ret;
+	struct storage_pps_entry	stde;
+
+	FIXME("(%lx, %p, 0x%08lx, %d, %lx, %p)\n", plkbyt, pstgPriority, grfMode, (int)snbExclude, reserved, ppstgOpen);
+	if ((plkbyt == 0) || (ppstgOpen == 0))
+		return STG_E_INVALIDPOINTER;
 
-  if ((plkbyt == 0) || (ppstgOpen == 0))
-    return STG_E_INVALIDPOINTER;
+	*ppstgOpen = 0;
 
-  *ppstgOpen = 0;
+	_create_istorage16(ppstgOpen);
+	lpstg = MapSL((SEGPTR)*ppstgOpen);
+	lpstg->str.hf = NULL;
+	lpstg->str.lockbytes = plkbyt;
+	i=0;ret=0;
+	while (!ret) { /* neither 1 nor <0 */
+		ret=STORAGE_get_pps_entry(&lpstg->str,i,&stde);
+		if ((ret==1) && (stde.pps_type==5)) {
+			lpstg->stde=stde;
+			break;
+		}
+		i++;
+	}
+	if (ret!=1) {
+		IStorage16_fnRelease((IStorage16*)lpstg); /* will remove it */
+		return E_FAIL;
+	}
+	return S_OK;
+}
 
-  _create_istorage16(ppstgOpen);
-  lpstg = MapSL((SEGPTR)*ppstgOpen);
+/***********************************************************************
+ *    ReadClassStg (OLE2.@)
+ *
+ * This method reads the CLSID previously written to a storage object with the WriteClassStg.
+ */
+HRESULT WINAPI ReadClassStg16(SEGPTR /*IStorage **/pstg,CLSID *pclsid){
+	STATSTG16 statstg;
+	HANDLE16 hstatstg;
+	HRESULT	hres;
+	DWORD args[3];
 
-  /* just teach it to use HANDLE instead of ilockbytes :/ */
+	TRACE("(%lx, %p)\n", pstg, pclsid);
 
-  return S_OK;
+	if(pclsid==NULL)
+		return E_POINTER;
+	/*
+	 * read a STATSTG structure (contains the clsid) from the storage
+	 */
+	args[0] = (DWORD)pstg;	/* iface */
+	args[1] = (DWORD)K32WOWGlobalAllocLock16( 0, sizeof(STATSTG16), &hstatstg );
+	args[2] = STATFLAG_DEFAULT;
+
+	if (!K32WOWCallback16Ex(
+	    (DWORD)((const IStorage16Vtbl*)MapSL(
+			(SEGPTR)((LPSTORAGE16)MapSL(pstg))->lpVtbl)
+	    )->Stat,
+	    WCB16_PASCAL,
+	    3*sizeof(DWORD),
+	    (LPVOID)args,
+	    (LPDWORD)&hres
+	)) {
+	    K32WOWGlobalUnlockFree16(args[1]);
+	    ERR("CallTo16 IStorage16::Stat() failed, hres %lx\n",hres);
+	    return hres;
+	}
+	memcpy(&statstg, MapSL(args[1]), sizeof(STATSTG16));
+	K32WOWGlobalUnlockFree16(args[1]);
+
+	if(SUCCEEDED(hres)) {
+		*pclsid=statstg.clsid;
+		TRACE("clsid is %s\n", debugstr_guid(&statstg.clsid));
+	}
+	return hres;
+}
+
+/***********************************************************************
+ *              GetConvertStg (OLE2.@)
+ */
+HRESULT WINAPI GetConvertStg16(IStorage *stg) {
+    FIXME("unimplemented stub!\n");
+    return E_FAIL;
 }
Index: dlls/ole32/storage.spec
===================================================================
RCS file: /home/wine/wine/dlls/ole32/storage.spec,v
retrieving revision 1.5
diff -u -r1.5 storage.spec
--- dlls/ole32/storage.spec	5 Jan 2003 01:04:34 -0000	1.5
+++ dlls/ole32/storage.spec	5 Aug 2005 20:38:20 -0000
@@ -6,7 +6,7 @@
 2 stub StgCreateDocFileOnILockBytes
 # 2 pascal StgCreateDocFileOnILockBytes(ptr long long ptr) StgCreateDocFileOnILockBytes16
 3 pascal StgOpenStorage(str ptr long ptr long ptr) StgOpenStorage16
-4 pascal StgOpenStorageOnILockBytes(ptr ptr long long long ptr) StgOpenStorageOnILockBytes16
+4 pascal StgOpenStorageOnILockBytes(segptr ptr long long long ptr) StgOpenStorageOnILockBytes16
 5 pascal StgIsStorageFile(str) StgIsStorageFile16
 6 pascal StgIsStorageILockBytes(segptr) StgIsStorageILockBytes16
 7 stub StgSetTimes



More information about the wine-patches mailing list