Add/fix more NT native API declarations.
[wine] / dlls / ole32 / storage.c
index ad3dee8..715c3e6 100644 (file)
@@ -5,29 +5,50 @@
  * (Thanks to Martin Schwartz <schwartz@cs.tu-berlin.de>)
  *
  * Copyright 1998 Marcus Meissner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "config.h"
+
 #include <assert.h>
 #include <time.h>
+#include <stdarg.h>
 #include <string.h>
 #include <sys/types.h>
-#include <unistd.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "windef.h"
-#include "ntddk.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
 #include "winerror.h"
-#include "wine/winestring.h"
 #include "wine/winbase16.h"
-#include "wingdi.h"
-#include "wtypes.h"
-#include "wine/obj_base.h"
-#include "wine/obj_storage.h"
-#include "heap.h"
-#include "module.h"
-#include "ldt.h"
-#include "debugtools.h"
-
-DEFAULT_DEBUG_CHANNEL(ole);
-DECLARE_DEBUG_CHANNEL(relay);
+#include "wownt32.h"
+#include "wine/unicode.h"
+#include "objbase.h"
+#include "wine/debug.h"
+
+#include "ifs.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+WINE_DECLARE_DEBUG_CHANNEL(relay);
 
 struct storage_header {
        BYTE    magic[8];       /* 00: magic */
@@ -62,19 +83,17 @@ struct storage_pps_entry {
 
 
 static const BYTE STORAGE_magic[8]   ={0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1};
-static const BYTE STORAGE_notmagic[8]={0x0e,0x11,0xfc,0x0d,0xd0,0xcf,0x11,0xe0};
-static const BYTE STORAGE_oldmagic[8]={0xd0,0xcf,0x11,0xe0,0x0e,0x11,0xfc,0x0d};
 
 #define BIGSIZE                512
 #define SMALLSIZE              64
 
 #define SMALLBLOCKS_PER_BIGBLOCK       (BIGSIZE/SMALLSIZE)
 
-#define READ_HEADER    assert(STORAGE_get_big_block(hf,-1,(LPBYTE)&sth));assert(!memcmp(STORAGE_magic,sth.magic,sizeof(STORAGE_magic)));
-static ICOM_VTABLE(IStorage16) stvt16;
-static ICOM_VTABLE(IStorage16) *segstvt16 = NULL;
-static ICOM_VTABLE(IStream16) strvt16;
-static ICOM_VTABLE(IStream16) *segstrvt16 = NULL;
+#define READ_HEADER    STORAGE_get_big_block(hf,-1,(LPBYTE)&sth);assert(!memcmp(STORAGE_magic,sth.magic,sizeof(STORAGE_magic)));
+static IStorage16Vtbl stvt16;
+static const IStorage16Vtbl *segstvt16 = NULL;
+static IStream16Vtbl strvt16;
+static const IStream16Vtbl *segstrvt16 = NULL;
 
 /*ULONG WINAPI IStorage16_AddRef(LPSTORAGE16 this);*/
 static void _create_istorage16(LPSTORAGE16 *stg);
@@ -82,6 +101,224 @@ static void _create_istream16(LPSTREAM16 *str);
 
 #define IMPLEMENTED 1
 
+/* The following is taken from the CorVu implementation of docfiles, and
+ * documents things about the file format that are not implemented here, and
+ * not documented by the LAOLA project. The CorVu implementation was posted
+ * to wine-devel in February 2004, and released under the LGPL at the same
+ * time. Because that implementation is in C++, it's not directly usable in
+ * Wine, but does have documentation value.
+ *
+ *
+ * #define DF_EXT_VTOC         -4
+ * #define DF_VTOC_VTOC                -3
+ * #define DF_VTOC_EOF         -2
+ * #define DF_VTOC_FREE                -1
+ * #define DF_NAMELEN  0x20    // Maximum entry name length - 31 characters plus
+ *                             // a NUL terminator
+ * 
+ * #define DF_FT_STORAGE       1
+ * #define DF_FT_STREAM                2
+ * #define DF_FT_LOCKBYTES     3       // Not used -- How the bloody hell did I manage
+ * #define DF_FT_PROPERTY      4       // Not Used -- to figure these two out?
+ * #define DF_FT_ROOT          5
+ * 
+ * #define DF_BLOCK_SIZE       0x200
+ * #define DF_VTOC_SIZE                0x80
+ * #define DF_DE_PER_BLOCK     4
+ * #define DF_STREAM_BLOCK_SIZE        0x40
+ * 
+ * A DocFile is divided into blocks of 512 bytes.
+ * The first block contains the header.
+ *
+ * The file header contains The first 109 entries in the VTOC of VTOCs.
+ *
+ * Each block pointed to by a VTOC of VTOCs contains a VTOC, which
+ * includes block chains - just like FAT. This is a somewhat poor
+ * design for the following reasons:
+ *
+ *     1. FAT was a poor file system design to begin with, and
+ *        has long been known to be horrendously inefficient
+ *        for day to day operations.
+ *
+ *     2. The problem is compounded here, since the file
+ *        level streams are generally *not* read sequentially.
+ *        This means that a significant percentage of reads
+ *        require seeking from the start of the chain.
+ *
+ * Data chains also contain an internal VTOC. The block size for
+ * the standard VTOC is 512. The block size for the internal VTOC
+ * is 64.
+ *
+ * Now, the 109 blocks in the VTOC of VTOCs allows for files of
+ * up to around 7MB. So what do you think happens if that's
+ * exceeded? Well, there's an entry in the header block which
+ * points to the first block used as additional storage for
+ * the VTOC of VTOCs.
+ *
+ * Now we can get up to around 15MB. Now, guess how the file
+ * format adds in another block to the VTOC of VTOCs. Come on,
+ * it's no big surprise. That's right - the last entry in each
+ * block extending the VTOC of VTOCs is, you guessed it, the
+ * block number of the next block containing an extension to
+ * the VTOC of VTOCs. The VTOC of VTOCs is chained!!!!
+ *
+ * So, to review:
+ *
+ * 1. If you are using a FAT file system, the location of
+ *    your file's blocks is stored in chains.
+ *
+ * 2. At the abstract level, the file contains a VTOC of VTOCs,
+ *    which is stored in the most inefficient possible format for
+ *    random access - a chain (AKA list).
+ *
+ * 3. The VTOC of VTOCs contains descriptions of three file level
+ *    streams:
+ *
+ *    a. The Directory stream
+ *    b. The Data stream
+ *    c. The Data VTOC stream
+ *
+ *    These are, of course, represented as chains.
+ *
+ * 4. The Data VTOC contains data describing the chains of blocks
+ *    within the Data stream.
+ *
+ * That's right - we have a total of four levels of block chains!
+ *
+ * Now, is that complicated enough for you? No? OK, there's another
+ * complication. If an individual stream (ie. an IStream) reaches
+ * 4096 bytes in size, it gets moved from the Data Stream to
+ * a new file level stream. Now, if the stream then gets truncated
+ * back to less than 4096 bytes, it returns to the data stream.
+ *
+ * The effect of using this format can be seen very easily. Pick
+ * an arbitrary application with a grid data representation that
+ * can export to both Lotus 123 and Excel 5 or higher. Export
+ * a large file to Lotus 123 and time it. Export the same thing
+ * to Excel 5 and time that. The difference is the inefficiency
+ * of the Microsoft DocFile format.
+ *
+ *
+ * #define TOTAL_SIMPLE_VTOCS  109
+ * 
+ * struct      DocFile_Header
+ * {
+ *     df_byte iMagic1;        // 0xd0 
+ *     df_byte iMagic2;        // 0xcf 
+ *     df_byte iMagic3;        // 0x11 
+ *     df_byte iMagic4;        // 0xe0 - Spells D0CF11E0, or DocFile 
+ *     df_byte iMagic5;        // 161  (igi upside down) 
+ *     df_byte iMagic6;        // 177  (lli upside down - see below 
+ *     df_byte iMagic7;        // 26 (gz upside down) 
+ *     df_byte iMagic8;        // 225 (szz upside down) - see below 
+ *     df_int4 aiUnknown1[4];
+ *     df_int4 iVersion;       // DocFile Version - 0x03003E   
+ *     df_int4 aiUnknown2[4];
+ *     df_int4 nVTOCs;         // Number of VTOCs 
+ *     df_int4 iFirstDirBlock; // First Directory Block 
+ *     df_int4 aiUnknown3[2];
+ *     df_int4 iFirstDataVTOC; // First data VTOC block 
+ *     df_int4 iHasData;       // 1 if there is data in the file - yes, this is important
+ *     df_int4 iExtendedVTOC;  // Extended VTOC location 
+ *     df_int4 iExtendedVTOCSize; // Size of extended VTOC (+1?) 
+ *     df_int4 aiVTOCofVTOCs[TOTAL_SIMPLE_VTOCS];
+ * };
+ * 
+ * struct      DocFile_VTOC
+ * {
+ *     df_int4 aiBlocks[DF_VTOC_SIZE];
+ * };
+ * 
+ * 
+ * The meaning of the magic numbers
+ *
+ * 0xd0cf11e0 is DocFile with a zero on the end (sort of)
+ *
+ * If you key 177161 into a calculator, then turn the calculator
+ * upside down, you get igilli, which may be a reference to
+ * somebody's name, or to the Hebrew word for "angel".
+ *
+ * If you key 26225 into a calculator, then turn it upside down, you
+ * get szzgz. Microsoft has a tradition of creating nonsense words
+ * using the letters s, g, z and y. We think szzgz may be one of the
+ * Microsoft placeholder variables, along the lines of foo, bar and baz.
+ * Alternatively, it could be 22526, which would be gzszz.
+ *
+ * 
+ * struct      DocFile_DirEnt
+ * {
+ *     df_char achEntryName[DF_NAMELEN];       // Entry Name 
+ *     df_int2 iNameLen;                       // Name length in bytes, including NUL terminator 
+ *     df_byte iFileType;                      // Entry type 
+ *     df_byte iColour;                        // 1 = Black, 0 = Red 
+ *     df_int4 iLeftSibling;                   // Next Left Sibling Entry - See below 
+ *     df_int4 iRightSibling;                  // Next Right Sibling Entry 
+ *     df_int4 iFirstChild;                    // First Child Entry 
+ *     df_byte achClassID[16];                 // Class ID 
+ *     df_int4 iStateBits;                     // [GS]etStateBits value 
+ *     df_int4 iCreatedLow;                    // Low DWORD of creation time 
+ *     df_int4 iCreatedHigh;                   // High DWORD of creation time 
+ *     df_int4 iModifiedLow;                   // Low DWORD of modification time 
+ *     df_int4 iModifiedHigh;                  // High DWORD of modification time 
+ *     df_int4 iVTOCPosition;                  // VTOC Position 
+ *     df_int4 iFileSize;                      // Size of the stream 
+ *     df_int4 iZero;                          // We think this is part of the 64 bit stream size - must be 0 
+ * };
+ * 
+ * Siblings
+ * ========
+ *
+ * Siblings are stored in an obscure but incredibly elegant
+ * data structure called a red-black tree. This is generally
+ * defined as a 2-3-4 tree stored in a binary tree.
+ *
+ * A red-black tree can always be balanced very easily. The rules
+ * for a red-black tree are as follows:
+ *
+ *     1. The root node is always black.
+ *     2. The parent of a red node is always black.
+ *
+ * There is a Java demo of red-black trees at:
+ *
+ *     http://langevin.usc.edu/BST/RedBlackTree-Example.html
+ *
+ * This demo is an excellent tool for learning how red-black
+ * trees work, without having to go through the process of
+ * learning how they were derived.
+ *
+ * Within the tree, elements are ordered by the length of the
+ * name and within that, ASCII order by name. This causes the
+ * apparently bizarre reordering you see when you use dfview.
+ *
+ * This is a somewhat bizarre choice. It suggests that the
+ * designer of the DocFile format was trying to optimise
+ * searching through the directory entries. However searching
+ * through directory entries is a relatively rare operation.
+ * Reading and seeking within a stream are much more common
+ * operations, especially within the file level streams, yet
+ * these use the horrendously inefficient FAT chains.
+ *
+ * This suggests that the designer was probably somebody
+ * fresh out of university, who had some basic knowledge of
+ * basic data structures, but little knowledge of anything
+ * more practical. It is bizarre to attempt to optimise
+ * directory searches while not using a more efficient file
+ * block locating system than FAT (seedling/sapling/tree
+ * would result in a massive improvement - in fact we have
+ * an alternative to DocFiles that we use internally that
+ * uses seedling/sapling/tree and *is* far more efficient).
+ *
+ * It is worth noting that the MS implementation of red-black
+ * trees is incorrect (I can tell you're surprised) and
+ * actually causes more operations to occur than are really
+ * needed. Fortunately the fact that our implementation is
+ * correct will not cause any problems - the MS implementation
+ * still appears to cause the tree to satisfy the rules, albeit
+ * a sequence of the same insertions in the different
+ * implementations may result in a different, and possibly
+ * deeper (but never shallower) tree.
+ */
+
 
 /******************************************************************************
  *             STORAGE_get_big_block   [Internal]
@@ -89,49 +326,58 @@ static void _create_istream16(LPSTREAM16 *str);
  * Reading OLE compound storage
  */
 static BOOL
-STORAGE_get_big_block(HFILE hf,int n,BYTE *block) {
-       assert(n>=-1);
-       if (-1==_llseek(hf,(n+1)*BIGSIZE,SEEK_SET)) {
-               WARN(" seek failed (%ld)\n",GetLastError());
-               return FALSE;
-       }
-       assert((n+1)*BIGSIZE==_llseek(hf,0,SEEK_CUR));
-       if (BIGSIZE!=_lread(hf,block,BIGSIZE)) {
-               WARN("(block size %d): read didn't read (%ld)\n",n,GetLastError());
-               assert(0);
-               return FALSE;
-       }
-       return TRUE;
+STORAGE_get_big_block(HANDLE hf,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 (!ReadFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE)
+    {
+        WARN("(block size %d): read didn't read (%ld)\n",n,GetLastError());
+        return FALSE;
+    }
+    return TRUE;
 }
 
 /******************************************************************************
  * STORAGE_put_big_block [INTERNAL]
  */
 static BOOL
-STORAGE_put_big_block(HFILE hf,int n,BYTE *block) {
-       assert(n>=-1);
-       if (-1==_llseek(hf,(n+1)*BIGSIZE,SEEK_SET)) {
-               WARN(" seek failed (%ld)\n",GetLastError());
-               return FALSE;
-       }
-       assert((n+1)*BIGSIZE==_llseek(hf,0,SEEK_CUR));
-       if (BIGSIZE!=_lwrite(hf,block,BIGSIZE)) {
-               WARN(" write failed (%ld)\n",GetLastError());
-               return FALSE;
-       }
-       return TRUE;
+STORAGE_put_big_block(HANDLE hf,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;
+    }
+    return TRUE;
 }
 
 /******************************************************************************
  * STORAGE_get_next_big_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_next_big_blocknr(HFILE hf,int blocknr) {
+STORAGE_get_next_big_blocknr(HANDLE hf,int blocknr) {
        INT     bbs[BIGSIZE/sizeof(INT)];
        struct  storage_header  sth;
 
        READ_HEADER;
-       
+
        assert(blocknr>>7<sth.num_of_bbd_blocks);
        if (sth.bbd_list[blocknr>>7]==0xffffffff)
                return -5;
@@ -145,13 +391,13 @@ STORAGE_get_next_big_blocknr(HFILE hf,int blocknr) {
  * STORAGE_get_nth_next_big_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_nth_next_big_blocknr(HFILE hf,int blocknr,int nr) {
+STORAGE_get_nth_next_big_blocknr(HANDLE hf,int blocknr,int nr) {
        INT     bbs[BIGSIZE/sizeof(INT)];
        int     lastblock = -1;
        struct storage_header sth;
 
        READ_HEADER;
-       
+
        assert(blocknr>=0);
        while (nr--) {
                assert((blocknr>>7)<sth.num_of_bbd_blocks);
@@ -159,7 +405,8 @@ STORAGE_get_nth_next_big_blocknr(HFILE hf,int blocknr,int nr) {
 
                /* simple caching... */
                if (lastblock!=sth.bbd_list[blocknr>>7]) {
-                       assert(STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs));
+                       BOOL ret = STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs);
+                       assert(ret);
                        lastblock = sth.bbd_list[blocknr>>7];
                }
                blocknr = bbs[blocknr&0x7f];
@@ -171,7 +418,7 @@ STORAGE_get_nth_next_big_blocknr(HFILE hf,int blocknr,int nr) {
  *             STORAGE_get_root_pps_entry      [Internal]
  */
 static BOOL
-STORAGE_get_root_pps_entry(HFILE hf,struct storage_pps_entry *pstde) {
+STORAGE_get_root_pps_entry(HANDLE hf,struct storage_pps_entry *pstde) {
        int     blocknr,i;
        BYTE    block[BIGSIZE];
        struct storage_pps_entry        *stde=(struct storage_pps_entry*)block;
@@ -180,7 +427,8 @@ STORAGE_get_root_pps_entry(HFILE hf,struct storage_pps_entry *pstde) {
        READ_HEADER;
        blocknr = sth.root_startblock;
        while (blocknr>=0) {
-               assert(STORAGE_get_big_block(hf,blocknr,block));
+               BOOL ret = STORAGE_get_big_block(hf,blocknr,block);
+               assert(ret);
                for (i=0;i<4;i++) {
                        if (!stde[i].pps_sizeofname)
                                continue;
@@ -198,16 +446,19 @@ STORAGE_get_root_pps_entry(HFILE hf,struct storage_pps_entry *pstde) {
  * STORAGE_get_small_block [INTERNAL]
  */
 static BOOL
-STORAGE_get_small_block(HFILE hf,int blocknr,BYTE *sblock) {
+STORAGE_get_small_block(HANDLE hf,int blocknr,BYTE *sblock) {
        BYTE                            block[BIGSIZE];
        int                             bigblocknr;
        struct storage_pps_entry        root;
+       BOOL ret;
 
        assert(blocknr>=0);
-       assert(STORAGE_get_root_pps_entry(hf,&root));
+       ret = STORAGE_get_root_pps_entry(hf,&root);
+       assert(ret);
        bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
        assert(bigblocknr>=0);
-       assert(STORAGE_get_big_block(hf,bigblocknr,block));
+       ret = STORAGE_get_big_block(hf,bigblocknr,block);
+       assert(ret);
 
        memcpy(sblock,((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),SMALLSIZE);
        return TRUE;
@@ -217,20 +468,24 @@ STORAGE_get_small_block(HFILE hf,int blocknr,BYTE *sblock) {
  * STORAGE_put_small_block [INTERNAL]
  */
 static BOOL
-STORAGE_put_small_block(HFILE hf,int blocknr,BYTE *sblock) {
+STORAGE_put_small_block(HANDLE hf,int blocknr,BYTE *sblock) {
        BYTE                            block[BIGSIZE];
        int                             bigblocknr;
        struct storage_pps_entry        root;
+       BOOL ret;
 
        assert(blocknr>=0);
 
-       assert(STORAGE_get_root_pps_entry(hf,&root));
+       ret = STORAGE_get_root_pps_entry(hf,&root);
+       assert(ret);
        bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
        assert(bigblocknr>=0);
-       assert(STORAGE_get_big_block(hf,bigblocknr,block));
+       ret = STORAGE_get_big_block(hf,bigblocknr,block);
+       assert(ret);
 
        memcpy(((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),sblock,SMALLSIZE);
-       assert(STORAGE_put_big_block(hf,bigblocknr,block));
+       ret = STORAGE_put_big_block(hf,bigblocknr,block);
+       assert(ret);
        return TRUE;
 }
 
@@ -238,17 +493,19 @@ STORAGE_put_small_block(HFILE hf,int blocknr,BYTE *sblock) {
  * STORAGE_get_next_small_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_next_small_blocknr(HFILE hf,int blocknr) {
+STORAGE_get_next_small_blocknr(HANDLE hf,int blocknr) {
        BYTE                            block[BIGSIZE];
        LPINT                           sbd = (LPINT)block;
        int                             bigblocknr;
        struct storage_header           sth;
+       BOOL ret;
 
        READ_HEADER;
        assert(blocknr>=0);
        bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
        assert(bigblocknr>=0);
-       assert(STORAGE_get_big_block(hf,bigblocknr,block));
+       ret = STORAGE_get_big_block(hf,bigblocknr,block);
+       assert(ret);
        assert(sbd[blocknr & 127]!=STORAGE_CHAINENTRY_FREE);
        return sbd[blocknr & (128-1)];
 }
@@ -257,21 +514,22 @@ STORAGE_get_next_small_blocknr(HFILE hf,int blocknr) {
  * STORAGE_get_nth_next_small_blocknr [INTERNAL]
  */
 static int
-STORAGE_get_nth_next_small_blocknr(HFILE hf,int blocknr,int nr) {
-       int     lastblocknr;
+STORAGE_get_nth_next_small_blocknr(HANDLE hf,int blocknr,int nr) {
+       int     lastblocknr=-1;
        BYTE    block[BIGSIZE];
        LPINT   sbd = (LPINT)block;
        struct storage_header sth;
+       BOOL ret;
 
        READ_HEADER;
-       lastblocknr=-1;
        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);
                        assert(bigblocknr>=0);
-                       assert(STORAGE_get_big_block(hf,bigblocknr,block));
+                       ret = STORAGE_get_big_block(hf,bigblocknr,block);
+                       assert(ret);
                        lastblocknr = blocknr;
                }
                assert(lastblocknr>=0);
@@ -286,17 +544,19 @@ STORAGE_get_nth_next_small_blocknr(HFILE hf,int blocknr,int nr) {
  * STORAGE_get_pps_entry [INTERNAL]
  */
 static int
-STORAGE_get_pps_entry(HFILE hf,int n,struct storage_pps_entry *pstde) {
+STORAGE_get_pps_entry(HANDLE hf,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;
        /* we have 4 pps entries per big block */
        blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4);
        assert(blocknr>=0);
-       assert(STORAGE_get_big_block(hf,blocknr,block));
+       ret = STORAGE_get_big_block(hf,blocknr,block);
+       assert(ret);
 
        *pstde=*stde;
        return 1;
@@ -306,20 +566,23 @@ STORAGE_get_pps_entry(HFILE hf,int n,struct storage_pps_entry *pstde) {
  *             STORAGE_put_pps_entry   [Internal]
  */
 static int
-STORAGE_put_pps_entry(HFILE hf,int n,struct storage_pps_entry *pstde) {
+STORAGE_put_pps_entry(HANDLE hf,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;
 
        /* we have 4 pps entries per big block */
        blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4);
        assert(blocknr>=0);
-       assert(STORAGE_get_big_block(hf,blocknr,block));
+       ret = STORAGE_get_big_block(hf,blocknr,block);
+       assert(ret);
        *stde=*pstde;
-       assert(STORAGE_put_big_block(hf,blocknr,block));
+       ret = STORAGE_put_big_block(hf,blocknr,block);
+       assert(ret);
        return 1;
 }
 
@@ -327,7 +590,7 @@ STORAGE_put_pps_entry(HFILE hf,int n,struct storage_pps_entry *pstde) {
  *             STORAGE_look_for_named_pps      [Internal]
  */
 static int
-STORAGE_look_for_named_pps(HFILE hf,int n,LPOLESTR name) {
+STORAGE_look_for_named_pps(HANDLE hf,int n,LPOLESTR name) {
        struct storage_pps_entry        stde;
        int                             ret;
 
@@ -361,7 +624,7 @@ void
 STORAGE_dump_pps_entry(struct storage_pps_entry *stde) {
     char       name[33];
 
-       lstrcpyWtoA(name,stde->pps_rawname);
+    WideCharToMultiByte( CP_ACP, 0, stde->pps_rawname, -1, name, sizeof(name), NULL, NULL);
        if (!stde->pps_sizeofname)
                return;
        DPRINTF("name: %s\n",name);
@@ -373,10 +636,10 @@ STORAGE_dump_pps_entry(struct storage_pps_entry *stde) {
        if (stde->pps_type !=2) {
                time_t  t;
                 DWORD dw;
-               RtlTimeToSecondsSince1970(&(stde->pps_ft1),&dw);
+               RtlTimeToSecondsSince1970((LARGE_INTEGER *)&(stde->pps_ft1),&dw);
                 t = dw;
                DPRINTF("ts1: %s\n",ctime(&t));
-               RtlTimeToSecondsSince1970(&(stde->pps_ft2),&dw);
+               RtlTimeToSecondsSince1970((LARGE_INTEGER *)&(stde->pps_ft2),&dw);
                 t = dw;
                DPRINTF("ts2: %s\n",ctime(&t));
        }
@@ -387,14 +650,15 @@ STORAGE_dump_pps_entry(struct storage_pps_entry *stde) {
 /******************************************************************************
  * STORAGE_init_storage [INTERNAL]
  */
-static BOOL 
-STORAGE_init_storage(HFILE hf) {
+static BOOL
+STORAGE_init_storage(HANDLE hf) {
        BYTE    block[BIGSIZE];
        LPDWORD bbs;
        struct storage_header *sth;
        struct storage_pps_entry *stde;
+        DWORD result;
 
-       assert(-1!=_llseek(hf,0,SEEK_SET));
+        SetFilePointer( hf, 0, NULL, SEEK_SET );
        /* block -1 is the storage header */
        sth = (struct storage_header*)block;
        memcpy(sth->magic,STORAGE_magic,8);
@@ -406,50 +670,53 @@ STORAGE_init_storage(HFILE hf) {
        sth->sbd_startblock     = 0xffffffff;
        memset(sth->bbd_list,0xff,sizeof(sth->bbd_list));
        sth->bbd_list[0]        = 0;
-       assert(BIGSIZE==_lwrite(hf,block,BIGSIZE));
+        if (!WriteFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE) 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 */
-       assert(BIGSIZE==_lwrite(hf,block,BIGSIZE));
+        if (!WriteFile( hf, block, BIGSIZE, &result, NULL ) || result != BIGSIZE) return FALSE;
        /* block 1 is the root directory entry */
        memset(block,0x00,sizeof(block));
        stde = (struct storage_pps_entry*)block;
-       lstrcpyAtoW(stde->pps_rawname,"RootEntry");
-       stde->pps_sizeofname    = lstrlenW(stde->pps_rawname)*2+2;
+        MultiByteToWideChar( CP_ACP, 0, "RootEntry", -1, stde->pps_rawname,
+                             sizeof(stde->pps_rawname)/sizeof(WCHAR));
+       stde->pps_sizeofname    = (strlenW(stde->pps_rawname)+1) * sizeof(WCHAR);
        stde->pps_type          = 5;
        stde->pps_dir           = -1;
        stde->pps_next          = -1;
        stde->pps_prev          = -1;
        stde->pps_sb            = 0xffffffff;
        stde->pps_size          = 0;
-       assert(BIGSIZE==_lwrite(hf,block,BIGSIZE));
-       return TRUE;
+        return (WriteFile( hf, block, BIGSIZE, &result, NULL ) && result == BIGSIZE);
 }
 
 /******************************************************************************
  *             STORAGE_set_big_chain   [Internal]
  */
 static BOOL
-STORAGE_set_big_chain(HFILE hf,int blocknr,INT type) {
+STORAGE_set_big_chain(HANDLE hf,int blocknr,INT type) {
        BYTE    block[BIGSIZE];
        LPINT   bbd = (LPINT)block;
        int     nextblocknr,bigblocknr;
        struct storage_header sth;
+       BOOL ret;
 
        READ_HEADER;
        assert(blocknr!=type);
        while (blocknr>=0) {
                bigblocknr = sth.bbd_list[blocknr/128];
                assert(bigblocknr>=0);
-               assert(STORAGE_get_big_block(hf,bigblocknr,block));
+               ret = STORAGE_get_big_block(hf,bigblocknr,block);
+               assert(ret);
 
                nextblocknr = bbd[blocknr&(128-1)];
                bbd[blocknr&(128-1)] = type;
                if (type>=0)
                        return TRUE;
-               assert(STORAGE_put_big_block(hf,bigblocknr,block));
+               ret = STORAGE_put_big_block(hf,bigblocknr,block);
+               assert(ret);
                type = STORAGE_CHAINENTRY_FREE;
                blocknr = nextblocknr;
        }
@@ -460,11 +727,12 @@ STORAGE_set_big_chain(HFILE hf,int blocknr,INT type) {
  * STORAGE_set_small_chain [Internal]
  */
 static BOOL
-STORAGE_set_small_chain(HFILE hf,int blocknr,INT type) {
+STORAGE_set_small_chain(HANDLE hf,int blocknr,INT type) {
        BYTE    block[BIGSIZE];
        LPINT   sbd = (LPINT)block;
        int     lastblocknr,nextsmallblocknr,bigblocknr;
        struct storage_header sth;
+       BOOL ret;
 
        READ_HEADER;
 
@@ -475,12 +743,14 @@ STORAGE_set_small_chain(HFILE hf,int blocknr,INT type) {
                if (lastblocknr/128!=blocknr/128) {
                        bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
                        assert(bigblocknr>=0);
-                       assert(STORAGE_get_big_block(hf,bigblocknr,block));
+                       ret = STORAGE_get_big_block(hf,bigblocknr,block);
+                       assert(ret);
                }
                lastblocknr = blocknr;
                nextsmallblocknr = sbd[blocknr&(128-1)];
                sbd[blocknr&(128-1)] = type;
-               assert(STORAGE_put_big_block(hf,bigblocknr,block));
+               ret = STORAGE_put_big_block(hf,bigblocknr,block);
+               assert(ret);
                if (type>=0)
                        return TRUE;
                type = STORAGE_CHAINENTRY_FREE;
@@ -492,12 +762,14 @@ STORAGE_set_small_chain(HFILE hf,int blocknr,INT type) {
 /******************************************************************************
  *             STORAGE_get_free_big_blocknr    [Internal]
  */
-static int 
-STORAGE_get_free_big_blocknr(HFILE hf) {
+static int
+STORAGE_get_free_big_blocknr(HANDLE hf) {
        BYTE    block[BIGSIZE];
        LPINT   sbd = (LPINT)block;
-       int     lastbigblocknr,i,curblock,bigblocknr;
+       int     lastbigblocknr,i,bigblocknr;
+       unsigned int curblock;
        struct storage_header sth;
+       BOOL ret;
 
        READ_HEADER;
        curblock        = 0;
@@ -505,45 +777,54 @@ STORAGE_get_free_big_blocknr(HFILE hf) {
        bigblocknr      = sth.bbd_list[curblock];
        while (curblock<sth.num_of_bbd_blocks) {
                assert(bigblocknr>=0);
-               assert(STORAGE_get_big_block(hf,bigblocknr,block));
+               ret = STORAGE_get_big_block(hf,bigblocknr,block);
+               assert(ret);
                for (i=0;i<128;i++)
                        if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
                                sbd[i] = STORAGE_CHAINENTRY_ENDOFCHAIN;
-                               assert(STORAGE_put_big_block(hf,bigblocknr,block));
+                               ret = STORAGE_put_big_block(hf,bigblocknr,block);
+                               assert(ret);
                                memset(block,0x42,sizeof(block));
-                               assert(STORAGE_put_big_block(hf,i+curblock*128,block));
+                               ret = STORAGE_put_big_block(hf,i+curblock*128,block);
+                               assert(ret);
                                return i+curblock*128;
                        }
                lastbigblocknr = bigblocknr;
                bigblocknr = sth.bbd_list[++curblock];
        }
        bigblocknr = curblock*128;
-       /* since we have marked all blocks from 0 up to curblock*128-1 
-        * the next free one is curblock*128, where we happily put our 
+       /* since we have marked all blocks from 0 up to curblock*128-1
+        * the next free one is curblock*128, where we happily put our
         * next large block depot.
         */
        memset(block,0xff,sizeof(block));
        /* mark the block allocated and returned by this function */
        sbd[1] = STORAGE_CHAINENTRY_ENDOFCHAIN;
-       assert(STORAGE_put_big_block(hf,bigblocknr,block));
+       ret = STORAGE_put_big_block(hf,bigblocknr,block);
+       assert(ret);
 
        /* if we had a bbd block already (mostlikely) we need
-        * to link the new one into the chain 
+        * to link the new one into the chain
         */
-       if (lastbigblocknr!=-1)
-               assert(STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr));
+       if (lastbigblocknr!=-1) {
+               ret = STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr);
+               assert(ret);
+       }
        sth.bbd_list[curblock]=bigblocknr;
        sth.num_of_bbd_blocks++;
        assert(sth.num_of_bbd_blocks==curblock+1);
-       assert(STORAGE_put_big_block(hf,-1,(LPBYTE)&sth));
+       ret = STORAGE_put_big_block(hf,-1,(LPBYTE)&sth);
+       assert(ret);
 
        /* Set the end of the chain for the bigblockdepots */
-       assert(STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN));
-       /* add 1, for the first entry is used for the additional big block 
+       ret = STORAGE_set_big_chain(hf,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) */
-       assert(STORAGE_put_big_block(hf,bigblocknr+1,block));
+       ret = STORAGE_put_big_block(hf,bigblocknr+1,block);
+       assert(ret);
        return bigblocknr+1;
 }
 
@@ -551,8 +832,8 @@ STORAGE_get_free_big_blocknr(HFILE hf) {
 /******************************************************************************
  *             STORAGE_get_free_small_blocknr  [Internal]
  */
-static int 
-STORAGE_get_free_small_blocknr(HFILE hf) {
+static int
+STORAGE_get_free_small_blocknr(HANDLE hf) {
        BYTE    block[BIGSIZE];
        LPINT   sbd = (LPINT)block;
        int     lastbigblocknr,newblocknr,i,curblock,bigblocknr;
@@ -634,8 +915,8 @@ STORAGE_get_free_small_blocknr(HFILE hf) {
  *             STORAGE_get_free_pps_entry      [Internal]
  */
 static int
-STORAGE_get_free_pps_entry(HFILE hf) {
-       int     blocknr,i,curblock,lastblocknr;
+STORAGE_get_free_pps_entry(HANDLE hf) {
+       int     blocknr, i, curblock, lastblocknr=-1;
        BYTE    block[BIGSIZE];
        struct storage_pps_entry *stde = (struct storage_pps_entry*)block;
        struct storage_header sth;
@@ -647,7 +928,7 @@ STORAGE_get_free_pps_entry(HFILE hf) {
        while (blocknr>=0) {
                if (!STORAGE_get_big_block(hf,blocknr,block))
                        return -1;
-               for (i=0;i<4;i++) 
+               for (i=0;i<4;i++)
                        if (stde[i].pps_sizeofname==0) /* free */
                                return curblock*4+i;
                lastblocknr = blocknr;
@@ -659,7 +940,7 @@ STORAGE_get_free_pps_entry(HFILE hf) {
        /* sth invalidated */
        if (blocknr<0)
                return -1;
-       
+
        if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
                return -1;
        if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
@@ -674,13 +955,13 @@ STORAGE_get_free_pps_entry(HFILE hf) {
 typedef struct
 {
         /* IUnknown fields */
-        ICOM_VFIELD(IStream16);
+        const IStream16Vtbl            *lpVtbl;
         DWORD                           ref;
         /* IStream16 fields */
         SEGPTR                          thisptr; /* pointer to this struct as segmented */
         struct storage_pps_entry        stde;
         int                             ppsent;
-        HFILE                         hf;
+        HANDLE                         hf;
         ULARGE_INTEGER                  offset;
 } IStream16Impl;
 
@@ -690,37 +971,38 @@ typedef struct
 HRESULT WINAPI IStream16_fnQueryInterface(
        IStream16* iface,REFIID refiid,LPVOID *obj
 ) {
-       ICOM_THIS(IStream16Impl,iface);
+       IStream16Impl *This = (IStream16Impl *)iface;
        TRACE_(relay)("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
        if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
                *obj = This;
                return 0;
        }
        return OLE_E_ENUM_NOMORE;
-       
+
 }
 
 /******************************************************************************
  * IStream16_AddRef [STORAGE.519]
  */
 ULONG WINAPI IStream16_fnAddRef(IStream16* iface) {
-       ICOM_THIS(IStream16Impl,iface);
-       return ++(This->ref);
+       IStream16Impl *This = (IStream16Impl *)iface;
+       return InterlockedIncrement(&This->ref);
 }
 
 /******************************************************************************
  * IStream16_Release [STORAGE.520]
  */
 ULONG WINAPI IStream16_fnRelease(IStream16* iface) {
-       ICOM_THIS(IStream16Impl,iface);
+       IStream16Impl *This = (IStream16Impl *)iface;
+        ULONG ref;
        FlushFileBuffers(This->hf);
-       This->ref--;
-       if (!This->ref) {
+        ref = InterlockedDecrement(&This->ref);
+       if (!ref) {
                CloseHandle(This->hf);
-               SEGPTR_FREE(This);
-               return 0;
+                UnMapLS( This->thisptr );
+               HeapFree( GetProcessHeap(), 0, This );
        }
-       return This->ref;
+       return ref;
 }
 
 /******************************************************************************
@@ -732,8 +1014,8 @@ ULONG WINAPI IStream16_fnRelease(IStream16* iface) {
 HRESULT WINAPI IStream16_fnSeek(
        IStream16* iface,LARGE_INTEGER offset,DWORD whence,ULARGE_INTEGER *newpos
 ) {
-       ICOM_THIS(IStream16Impl,iface);
-       TRACE_(relay)("(%p)->([%ld.%ld],%ld,%p)\n",This,offset.s.HighPart,offset.s.LowPart,whence,newpos);
+       IStream16Impl *This = (IStream16Impl *)iface;
+       TRACE_(relay)("(%p)->([%ld.%ld],%ld,%p)\n",This,offset.u.HighPart,offset.u.LowPart,whence,newpos);
 
        switch (whence) {
        /* unix SEEK_xx should be the same as win95 ones */
@@ -741,31 +1023,31 @@ HRESULT WINAPI IStream16_fnSeek(
                /* offset must be ==0 (<0 is invalid, and >0 cannot be handled
                 * right now.
                 */
-               assert(offset.s.HighPart==0);
-               This->offset.s.HighPart = offset.s.HighPart;
-               This->offset.s.LowPart = offset.s.LowPart;
+               assert(offset.u.HighPart==0);
+               This->offset.u.HighPart = offset.u.HighPart;
+               This->offset.u.LowPart = offset.u.LowPart;
                break;
        case SEEK_CUR:
-               if (offset.s.HighPart < 0) {
+               if (offset.u.HighPart < 0) {
                        /* FIXME: is this negation correct ? */
-                       offset.s.HighPart = -offset.s.HighPart;
-                       offset.s.LowPart = (0xffffffff ^ offset.s.LowPart)+1;
+                       offset.u.HighPart = -offset.u.HighPart;
+                       offset.u.LowPart = (0xffffffff ^ offset.u.LowPart)+1;
 
-                       assert(offset.s.HighPart==0);
-                       assert(This->offset.s.LowPart >= offset.s.LowPart);
-                       This->offset.s.LowPart -= offset.s.LowPart;
+                       assert(offset.u.HighPart==0);
+                       assert(This->offset.u.LowPart >= offset.u.LowPart);
+                       This->offset.u.LowPart -= offset.u.LowPart;
                } else {
-                       assert(offset.s.HighPart==0);
-                       This->offset.s.LowPart+= offset.s.LowPart;
+                       assert(offset.u.HighPart==0);
+                       This->offset.u.LowPart+= offset.u.LowPart;
                }
                break;
        case SEEK_END:
-               assert(offset.s.HighPart==0);
-               This->offset.s.LowPart = This->stde.pps_size-offset.s.LowPart;
+               assert(offset.u.HighPart==0);
+               This->offset.u.LowPart = This->stde.pps_size-offset.u.LowPart;
                break;
        }
-       if (This->offset.s.LowPart>This->stde.pps_size)
-               This->offset.s.LowPart=This->stde.pps_size;
+       if (This->offset.u.LowPart>This->stde.pps_size)
+               This->offset.u.LowPart=This->stde.pps_size;
        if (newpos) *newpos = This->offset;
        return S_OK;
 }
@@ -776,53 +1058,54 @@ HRESULT WINAPI IStream16_fnSeek(
 HRESULT WINAPI IStream16_fnRead(
         IStream16* iface,void  *pv,ULONG cb,ULONG  *pcbRead
 ) {
-       ICOM_THIS(IStream16Impl,iface);
+       IStream16Impl *This = (IStream16Impl *)iface;
        BYTE    block[BIGSIZE];
        ULONG   *bytesread=pcbRead,xxread;
        int     blocknr;
+       LPBYTE  pbv = pv;
 
        TRACE_(relay)("(%p)->(%p,%ld,%p)\n",This,pv,cb,pcbRead);
        if (!pcbRead) bytesread=&xxread;
        *bytesread = 0;
 
-       if (cb>This->stde.pps_size-This->offset.s.LowPart)
-               cb=This->stde.pps_size-This->offset.s.LowPart;
+       if (cb>This->stde.pps_size-This->offset.u.LowPart)
+               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.s.LowPart/SMALLSIZE);
+               blocknr = STORAGE_get_nth_next_small_blocknr(This->hf,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
                while (cb) {
-                       int     cc;
+                       unsigned int cc;
 
                        if (!STORAGE_get_small_block(This->hf,blocknr,block)) {
                           WARN("small block read failed!!!\n");
                                return E_FAIL;
                        }
-                       cc = cb; 
-                       if (cc>SMALLSIZE-(This->offset.s.LowPart&(SMALLSIZE-1)))
-                               cc=SMALLSIZE-(This->offset.s.LowPart&(SMALLSIZE-1));
-                       memcpy((LPBYTE)pv,block+(This->offset.s.LowPart&(SMALLSIZE-1)),cc);
-                       This->offset.s.LowPart+=cc;
-                       (LPBYTE)pv+=cc;
+                       cc = cb;
+                       if (cc>SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1)))
+                               cc=SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1));
+                       memcpy(pbv,block+(This->offset.u.LowPart&(SMALLSIZE-1)),cc);
+                       This->offset.u.LowPart+=cc;
+                       pbv+=cc;
                        *bytesread+=cc;
                        cb-=cc;
                        blocknr = STORAGE_get_next_small_blocknr(This->hf,blocknr);
                }
        } else {
                /* use big block reader */
-               blocknr = STORAGE_get_nth_next_big_blocknr(This->hf,This->stde.pps_sb,This->offset.s.LowPart/BIGSIZE);
+               blocknr = STORAGE_get_nth_next_big_blocknr(This->hf,This->stde.pps_sb,This->offset.u.LowPart/BIGSIZE);
                while (cb) {
-                       int     cc;
+                       unsigned int cc;
 
                        if (!STORAGE_get_big_block(This->hf,blocknr,block)) {
                                WARN("big block read failed!!!\n");
                                return E_FAIL;
                        }
-                       cc = cb; 
-                       if (cc>BIGSIZE-(This->offset.s.LowPart&(BIGSIZE-1)))
-                               cc=BIGSIZE-(This->offset.s.LowPart&(BIGSIZE-1));
-                       memcpy((LPBYTE)pv,block+(This->offset.s.LowPart&(BIGSIZE-1)),cc);
-                       This->offset.s.LowPart+=cc;
-                       (LPBYTE)pv+=cc;
+                       cc = cb;
+                       if (cc>BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1)))
+                               cc=BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1));
+                       memcpy(pbv,block+(This->offset.u.LowPart&(BIGSIZE-1)),cc);
+                       This->offset.u.LowPart+=cc;
+                       pbv+=cc;
                        *bytesread+=cc;
                        cb-=cc;
                        blocknr=STORAGE_get_next_big_blocknr(This->hf,blocknr);
@@ -837,18 +1120,19 @@ HRESULT WINAPI IStream16_fnRead(
 HRESULT WINAPI IStream16_fnWrite(
         IStream16* iface,const void *pv,ULONG cb,ULONG *pcbWrite
 ) {
-       ICOM_THIS(IStream16Impl,iface);
+       IStream16Impl *This = (IStream16Impl *)iface;
        BYTE    block[BIGSIZE];
        ULONG   *byteswritten=pcbWrite,xxwritten;
        int     oldsize,newsize,i,curoffset=0,lastblocknr,blocknr,cc;
-       HFILE   hf = This->hf;
+       HANDLE  hf = This->hf;
+       const BYTE*     pbv = (const BYTE*)pv;
 
        if (!pcbWrite) byteswritten=&xxwritten;
        *byteswritten = 0;
 
        TRACE_(relay)("(%p)->(%p,%ld,%p)\n",This,pv,cb,pcbWrite);
        /* do we need to junk some blocks? */
-       newsize = This->offset.s.LowPart+cb;
+       newsize = This->offset.u.LowPart+cb;
        oldsize = This->stde.pps_size;
        if (newsize < oldsize) {
                if (oldsize < 0x1000) {
@@ -869,10 +1153,12 @@ HRESULT WINAPI IStream16_fnWrite(
                                if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
                                        return E_FAIL;
                        } else {
-                               /* Migrate large blocks to small blocks 
+                               /* Migrate large blocks to small blocks
                                 * (we just migrate newsize bytes)
                                 */
                                LPBYTE  curdata,data = HeapAlloc(GetProcessHeap(),0,newsize+BIGSIZE);
+                               HRESULT r = E_FAIL;
+
                                cc      = newsize;
                                blocknr = This->stde.pps_sb;
                                curdata = data;
@@ -887,31 +1173,35 @@ HRESULT WINAPI IStream16_fnWrite(
                                }
                                /* frees complete chain for this stream */
                                if (!STORAGE_set_big_chain(hf,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
-                                       return E_FAIL;
+                                       goto err;
                                curdata = data;
                                blocknr = This->stde.pps_sb = STORAGE_get_free_small_blocknr(hf);
                                if (blocknr<0)
-                                       return E_FAIL;
+                                       goto err;
                                cc      = newsize;
                                while (cc>0) {
                                        if (!STORAGE_put_small_block(hf,blocknr,curdata))
-                                               return E_FAIL;
+                                               goto err;
                                        cc      -= SMALLSIZE;
                                        if (cc<=0) {
                                                if (!STORAGE_set_small_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
-                                                       return E_FAIL;
+                                                       goto err;
                                                break;
                                        } else {
                                                int newblocknr = STORAGE_get_free_small_blocknr(hf);
                                                if (newblocknr<0)
-                                                       return E_FAIL;
+                                                       goto err;
                                                if (!STORAGE_set_small_chain(hf,blocknr,newblocknr))
-                                                       return E_FAIL;
+                                                       goto err;
                                                blocknr = newblocknr;
                                        }
                                        curdata += SMALLSIZE;
                                }
+                               r = S_OK;
+                       err:
                                HeapFree(GetProcessHeap(),0,data);
+                               if(r != S_OK)
+                                       return r;
                        }
                }
                This->stde.pps_size = newsize;
@@ -966,47 +1256,51 @@ HRESULT WINAPI IStream16_fnWrite(
                                } else {
                                        /* Migrate small blocks to big blocks */
                                        LPBYTE  curdata,data = HeapAlloc(GetProcessHeap(),0,oldsize+BIGSIZE);
+                                       HRESULT r = E_FAIL;
+
                                        cc      = oldsize;
                                        blocknr = This->stde.pps_sb;
                                        curdata = data;
                                        /* slurp in */
                                        while (cc>0) {
-                                               if (!STORAGE_get_small_block(hf,blocknr,curdata)) {
-                                                       HeapFree(GetProcessHeap(),0,data);
-                                                       return E_FAIL;
-                                               }
+                                               if (!STORAGE_get_small_block(hf,blocknr,curdata))
+                                                       goto err2;
                                                curdata += SMALLSIZE;
                                                cc      -= SMALLSIZE;
                                                blocknr  = STORAGE_get_next_small_blocknr(hf,blocknr);
                                        }
                                        /* free small block chain */
                                        if (!STORAGE_set_small_chain(hf,This->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
-                                               return E_FAIL;
+                                               goto err2;
                                        curdata = data;
                                        blocknr = This->stde.pps_sb = STORAGE_get_free_big_blocknr(hf);
                                        if (blocknr<0)
-                                               return E_FAIL;
+                                               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))
-                                                       return E_FAIL;
+                                                       goto err2;
                                                cc      -= BIGSIZE;
                                                if (cc<=0) {
                                                        if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
-                                                               return E_FAIL;
+                                                               goto err2;
                                                        break;
                                                } else {
                                                        int newblocknr = STORAGE_get_free_big_blocknr(hf);
                                                        if (newblocknr<0)
-                                                               return E_FAIL;
+                                                               goto err2;
                                                        if (!STORAGE_set_big_chain(hf,blocknr,newblocknr))
-                                                               return E_FAIL;
+                                                               goto err2;
                                                        blocknr = newblocknr;
                                                }
                                                curdata += BIGSIZE;
                                        }
+                                       r = S_OK;
+                               err2:
                                        HeapFree(GetProcessHeap(),0,data);
+                                       if(r != S_OK)
+                                               return r;
                                }
                                /* generate big blocks to fit the new data */
                                lastblocknr     = blocknr;
@@ -1034,7 +1328,7 @@ HRESULT WINAPI IStream16_fnWrite(
 
        /* finally the write pass */
        if (This->stde.pps_size < 0x1000) {
-               blocknr = STORAGE_get_nth_next_small_blocknr(hf,This->stde.pps_sb,This->offset.s.LowPart/SMALLSIZE);
+               blocknr = STORAGE_get_nth_next_small_blocknr(hf,This->stde.pps_sb,This->offset.u.LowPart/SMALLSIZE);
                assert(blocknr>=0);
                while (cb>0) {
                        /* we ensured that it is allocated above */
@@ -1045,24 +1339,24 @@ HRESULT WINAPI IStream16_fnWrite(
                        if (!STORAGE_get_small_block(hf,blocknr,block))
                                return E_FAIL;
 
-                       cc = SMALLSIZE-(This->offset.s.LowPart&(SMALLSIZE-1));
+                       cc = SMALLSIZE-(This->offset.u.LowPart&(SMALLSIZE-1));
                        if (cc>cb)
                                cc=cb;
-                       memcpy( ((LPBYTE)block)+(This->offset.s.LowPart&(SMALLSIZE-1)),
-                               (LPBYTE)((char *) pv+curoffset),
+                       memcpy( ((LPBYTE)block)+(This->offset.u.LowPart&(SMALLSIZE-1)),
+                               pbv+curoffset,
                                cc
                        );
                        if (!STORAGE_put_small_block(hf,blocknr,block))
                                return E_FAIL;
                        cb                      -= cc;
                        curoffset               += cc;
-                       (LPBYTE)pv              += cc;
-                       This->offset.s.LowPart  += cc;
+                       pbv                     += cc;
+                       This->offset.u.LowPart  += cc;
                        *byteswritten           += cc;
                        blocknr = STORAGE_get_next_small_blocknr(hf,blocknr);
                }
        } else {
-               blocknr = STORAGE_get_nth_next_big_blocknr(hf,This->stde.pps_sb,This->offset.s.LowPart/BIGSIZE);
+               blocknr = STORAGE_get_nth_next_big_blocknr(hf,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 */
@@ -1073,19 +1367,19 @@ HRESULT WINAPI IStream16_fnWrite(
                        if (!STORAGE_get_big_block(hf,blocknr,block))
                                return E_FAIL;
 
-                       cc = BIGSIZE-(This->offset.s.LowPart&(BIGSIZE-1));
+                       cc = BIGSIZE-(This->offset.u.LowPart&(BIGSIZE-1));
                        if (cc>cb)
                                cc=cb;
-                       memcpy( ((LPBYTE)block)+(This->offset.s.LowPart&(BIGSIZE-1)),
-                               (LPBYTE)((char *) pv+curoffset),
+                       memcpy( ((LPBYTE)block)+(This->offset.u.LowPart&(BIGSIZE-1)),
+                               pbv+curoffset,
                                cc
                        );
                        if (!STORAGE_put_big_block(hf,blocknr,block))
                                return E_FAIL;
                        cb                      -= cc;
                        curoffset               += cc;
-                       (LPBYTE)pv              += cc;
-                       This->offset.s.LowPart  += cc;
+                       pbv                     += cc;
+                       This->offset.u.LowPart  += cc;
                        *byteswritten           += cc;
                        blocknr = STORAGE_get_next_big_blocknr(hf,blocknr);
                }
@@ -1099,11 +1393,11 @@ HRESULT WINAPI IStream16_fnWrite(
 static void _create_istream16(LPSTREAM16 *str) {
        IStream16Impl*  lpst;
 
-       if (!strvt16.fnQueryInterface) {
+       if (!strvt16.QueryInterface) {
                HMODULE16       wp = GetModuleHandle16("STORAGE");
                if (wp>=32) {
                  /* FIXME: what is This GetProcAddress16. Should the name be IStream16_QueryInterface of IStream16_fnQueryInterface */
-#define VTENT(xfn)  strvt16.fn##xfn = (void*)GetProcAddress16(wp,"IStream16_"#xfn);assert(strvt16.fn##xfn)
+#define VTENT(xfn)  strvt16.xfn = (void*)GetProcAddress16(wp,"IStream16_"#xfn);assert(strvt16.xfn)
                        VTENT(QueryInterface);
                        VTENT(AddRef);
                        VTENT(Release);
@@ -1119,11 +1413,9 @@ static void _create_istream16(LPSTREAM16 *str) {
                        VTENT(Stat);
                        VTENT(Clone);
 #undef VTENT
-                       segstrvt16 = SEGPTR_NEW(ICOM_VTABLE(IStream16));
-                       memcpy(segstrvt16,&strvt16,sizeof(strvt16));
-                       segstrvt16 = (ICOM_VTABLE(IStream16)*)SEGPTR_GET(segstrvt16);
+                       segstrvt16 = (const IStream16Vtbl*)MapLS( &strvt16 );
                } else {
-#define VTENT(xfn) strvt16.fn##xfn = IStream16_fn##xfn;
+#define VTENT(xfn) strvt16.xfn = IStream16_fn##xfn;
                        VTENT(QueryInterface);
                        VTENT(AddRef);
                        VTENT(Release);
@@ -1144,10 +1436,10 @@ static void _create_istream16(LPSTREAM16 *str) {
                        segstrvt16 = &strvt16;
                }
        }
-       lpst = SEGPTR_NEW(IStream16Impl);
-       ICOM_VTBL(lpst) = segstrvt16;
+       lpst = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpst) );
+       lpst->lpVtbl    = segstrvt16;
        lpst->ref       = 1;
-       lpst->thisptr   = SEGPTR_GET(lpst);
+       lpst->thisptr   = MapLS( lpst );
        *str = (void*)lpst->thisptr;
 }
 
@@ -1157,12 +1449,12 @@ static void _create_istream16(LPSTREAM16 *str) {
 typedef struct
 {
         /* IUnknown fields */
-        ICOM_VFIELD(IStream);
+        const IStreamVtbl              *lpVtbl;
         DWORD                           ref;
         /* IStream32 fields */
         struct storage_pps_entry        stde;
         int                             ppsent;
-        HFILE                         hf;
+        HANDLE                         hf;
         ULARGE_INTEGER                  offset;
 } IStream32Impl;
 
@@ -1172,7 +1464,7 @@ typedef struct
 HRESULT WINAPI IStream_fnQueryInterface(
        IStream* iface,REFIID refiid,LPVOID *obj
 ) {
-       ICOM_THIS(IStream32Impl,iface);
+       IStream32Impl *This = (IStream32Impl *)iface;
 
        TRACE_(relay)("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
        if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
@@ -1180,30 +1472,30 @@ HRESULT WINAPI IStream_fnQueryInterface(
                return 0;
        }
        return OLE_E_ENUM_NOMORE;
-       
+
 }
 
 /******************************************************************************
  * IStream32_AddRef [VTABLE]
  */
 ULONG WINAPI IStream_fnAddRef(IStream* iface) {
-       ICOM_THIS(IStream32Impl,iface);
-       return ++(This->ref);
+       IStream32Impl *This = (IStream32Impl *)iface;
+       return InterlockedIncrement(&This->ref);
 }
 
 /******************************************************************************
  * IStream32_Release [VTABLE]
  */
 ULONG WINAPI IStream_fnRelease(IStream* iface) {
-       ICOM_THIS(IStream32Impl,iface);
+       IStream32Impl *This = (IStream32Impl *)iface;
+        ULONG ref;
        FlushFileBuffers(This->hf);
-       This->ref--;
-       if (!This->ref) {
+        ref = InterlockedDecrement(&This->ref);
+       if (!ref) {
                CloseHandle(This->hf);
-               SEGPTR_FREE(This);
-               return 0;
+               HeapFree( GetProcessHeap(), 0, This );
        }
-       return This->ref;
+       return ref;
 }
 
 /* --- IStorage16 implementation */
@@ -1211,13 +1503,13 @@ ULONG WINAPI IStream_fnRelease(IStream* iface) {
 typedef struct
 {
         /* IUnknown fields */
-        ICOM_VFIELD(IStorage16);
+        const IStorage16Vtbl           *lpVtbl;
         DWORD                           ref;
         /* IStorage16 fields */
         SEGPTR                          thisptr; /* pointer to this struct as segmented */
         struct storage_pps_entry        stde;
         int                             ppsent;
-        HFILE                         hf;
+        HANDLE                         hf;
 } IStorage16Impl;
 
 /******************************************************************************
@@ -1226,7 +1518,7 @@ typedef struct
 HRESULT WINAPI IStorage16_fnQueryInterface(
        IStorage16* iface,REFIID refiid,LPVOID *obj
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
 
        TRACE_(relay)("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
 
@@ -1241,20 +1533,23 @@ HRESULT WINAPI IStorage16_fnQueryInterface(
  * IStorage16_AddRef [STORAGE.501]
  */
 ULONG WINAPI IStorage16_fnAddRef(IStorage16* iface) {
-       ICOM_THIS(IStorage16Impl,iface);
-       return ++(This->ref);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
+       return InterlockedIncrement(&This->ref);
 }
 
 /******************************************************************************
  * IStorage16_Release [STORAGE.502]
  */
 ULONG WINAPI IStorage16_fnRelease(IStorage16* iface) {
-       ICOM_THIS(IStorage16Impl,iface);
-       This->ref--;
-       if (This->ref)
-               return This->ref;
-       SEGPTR_FREE(This);
-       return 0;
+       IStorage16Impl *This = (IStorage16Impl *)iface;
+        ULONG ref;
+        ref = InterlockedDecrement(&This->ref);
+        if (!ref)
+        {
+            UnMapLS( This->thisptr );
+            HeapFree( GetProcessHeap(), 0, This );
+        }
+        return ref;
 }
 
 /******************************************************************************
@@ -1263,13 +1558,17 @@ ULONG WINAPI IStorage16_fnRelease(IStorage16* iface) {
 HRESULT WINAPI IStorage16_fnStat(
         LPSTORAGE16 iface,STATSTG16 *pstatstg, DWORD grfStatFlag
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
+        DWORD len = WideCharToMultiByte( CP_ACP, 0, This->stde.pps_rawname, -1, NULL, 0, NULL, NULL );
+        LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, len );
+
        TRACE("(%p)->(%p,0x%08lx)\n",
                This,pstatstg,grfStatFlag
        );
-       pstatstg->pwcsName=(LPOLESTR16)SEGPTR_GET(SEGPTR_STRDUP_WtoA(This->stde.pps_rawname));
+        WideCharToMultiByte( CP_ACP, 0, This->stde.pps_rawname, -1, nameA, len, NULL, NULL );
+       pstatstg->pwcsName=(LPOLESTR16)MapLS( nameA );
        pstatstg->type = This->stde.pps_type;
-       pstatstg->cbSize.s.LowPart = This->stde.pps_size;
+       pstatstg->cbSize.u.LowPart = This->stde.pps_size;
        pstatstg->mtime = This->stde.pps_ft1; /* FIXME */ /* why? */
        pstatstg->atime = This->stde.pps_ft2; /* FIXME */
        pstatstg->ctime = This->stde.pps_ft2; /* FIXME */
@@ -1287,7 +1586,7 @@ HRESULT WINAPI IStorage16_fnStat(
 HRESULT WINAPI IStorage16_fnCommit(
         LPSTORAGE16 iface,DWORD commitflags
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
        FIXME("(%p)->(0x%08lx),STUB!\n",
                This,commitflags
        );
@@ -1298,7 +1597,7 @@ HRESULT WINAPI IStorage16_fnCommit(
  * IStorage16_CopyTo [STORAGE.507]
  */
 HRESULT WINAPI IStorage16_fnCopyTo(LPSTORAGE16 iface,DWORD ciidExclude,const IID *rgiidExclude,SNB16 SNB16Exclude,IStorage16 *pstgDest) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
        FIXME("IStorage16(%p)->(0x%08lx,%s,%p,%p),stub!\n",
                This,ciidExclude,debugstr_guid(rgiidExclude),SNB16Exclude,pstgDest
        );
@@ -1312,12 +1611,14 @@ HRESULT WINAPI IStorage16_fnCopyTo(LPSTORAGE16 iface,DWORD ciidExclude,const IID
 HRESULT WINAPI IStorage16_fnCreateStorage(
        LPSTORAGE16 iface,LPCOLESTR16 pwcsName,DWORD grfMode,DWORD dwStgFormat,DWORD reserved2, IStorage16 **ppstg
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
        IStorage16Impl* lpstg;
        int             ppsent,x;
        struct storage_pps_entry        stde;
        struct storage_header sth;
-       HFILE           hf=This->hf;
+       HANDLE          hf=This->hf;
+       BOOL ret;
+       int      nPPSEntries;
 
        READ_HEADER;
 
@@ -1327,7 +1628,7 @@ HRESULT WINAPI IStorage16_fnCreateStorage(
        if (grfMode & STGM_TRANSACTED)
                FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
        _create_istorage16(ppstg);
-       lpstg = (IStorage16Impl*)PTR_SEG_TO_LIN(*ppstg);
+       lpstg = MapSL((SEGPTR)*ppstg);
        lpstg->hf               = This->hf;
 
        ppsent=STORAGE_get_free_pps_entry(lpstg->hf);
@@ -1349,10 +1650,13 @@ HRESULT WINAPI IStorage16_fnCreateStorage(
                }
                stde.pps_next = ppsent;
        }
-       assert(STORAGE_put_pps_entry(lpstg->hf,x,&stde));
-       assert(1==STORAGE_get_pps_entry(lpstg->hf,ppsent,&(lpstg->stde)));
-       lstrcpyAtoW(lpstg->stde.pps_rawname,pwcsName);
-       lpstg->stde.pps_sizeofname = strlen(pwcsName)*2+2;
+       ret = STORAGE_put_pps_entry(lpstg->hf,x,&stde);
+       assert(ret);
+       nPPSEntries = STORAGE_get_pps_entry(lpstg->hf,ppsent,&(lpstg->stde));
+       assert(nPPSEntries == 1);
+        MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, lpstg->stde.pps_rawname,
+                             sizeof(lpstg->stde.pps_rawname)/sizeof(WCHAR));
+       lpstg->stde.pps_sizeofname = (strlenW(lpstg->stde.pps_rawname)+1)*sizeof(WCHAR);
        lpstg->stde.pps_next    = -1;
        lpstg->stde.pps_prev    = -1;
        lpstg->stde.pps_dir     = -1;
@@ -1372,10 +1676,12 @@ HRESULT WINAPI IStorage16_fnCreateStorage(
 HRESULT WINAPI IStorage16_fnCreateStream(
        LPSTORAGE16 iface,LPCOLESTR16 pwcsName,DWORD grfMode,DWORD reserved1,DWORD reserved2, IStream16 **ppstm
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
        IStream16Impl*  lpstr;
        int             ppsent,x;
        struct storage_pps_entry        stde;
+       BOOL ret;
+       int      nPPSEntries;
 
        TRACE("(%p)->(%s,0x%08lx,0x%08lx,0x%08lx,%p)\n",
                This,pwcsName,grfMode,reserved1,reserved2,ppstm
@@ -1383,11 +1689,11 @@ HRESULT WINAPI IStorage16_fnCreateStream(
        if (grfMode & STGM_TRANSACTED)
                FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
        _create_istream16(ppstm);
-       lpstr = (IStream16Impl*)PTR_SEG_TO_LIN(*ppstm);
+       lpstr = MapSL((SEGPTR)*ppstm);
         DuplicateHandle( GetCurrentProcess(), This->hf, GetCurrentProcess(),
                          &lpstr->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
-       lpstr->offset.s.LowPart = 0;
-       lpstr->offset.s.HighPart        = 0;
+       lpstr->offset.u.LowPart = 0;
+       lpstr->offset.u.HighPart        = 0;
 
        ppsent=STORAGE_get_free_pps_entry(lpstr->hf);
        if (ppsent<0)
@@ -1402,10 +1708,13 @@ HRESULT WINAPI IStorage16_fnCreateStream(
                                return E_FAIL;
                }
        stde.pps_next = ppsent;
-       assert(STORAGE_put_pps_entry(lpstr->hf,x,&stde));
-       assert(1==STORAGE_get_pps_entry(lpstr->hf,ppsent,&(lpstr->stde)));
-       lstrcpyAtoW(lpstr->stde.pps_rawname,pwcsName);
-       lpstr->stde.pps_sizeofname = strlen(pwcsName)*2+2;
+       ret = STORAGE_put_pps_entry(lpstr->hf,x,&stde);
+       assert(ret);
+       nPPSEntries = STORAGE_get_pps_entry(lpstr->hf,ppsent,&(lpstr->stde));
+       assert(nPPSEntries == 1);
+        MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, lpstr->stde.pps_rawname,
+                             sizeof(lpstr->stde.pps_rawname)/sizeof(WCHAR));
+       lpstr->stde.pps_sizeofname = (strlenW(lpstr->stde.pps_rawname)+1) * sizeof(WCHAR);
        lpstr->stde.pps_next    = -1;
        lpstr->stde.pps_prev    = -1;
        lpstr->stde.pps_dir     = -1;
@@ -1425,7 +1734,7 @@ HRESULT WINAPI IStorage16_fnCreateStream(
 HRESULT WINAPI IStorage16_fnOpenStorage(
        LPSTORAGE16 iface,LPCOLESTR16 pwcsName, IStorage16 *pstgPrio, DWORD grfMode, SNB16 snbExclude, DWORD reserved, IStorage16 **ppstg
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
        IStream16Impl*  lpstg;
        WCHAR           name[33];
        int             newpps;
@@ -1436,10 +1745,10 @@ HRESULT WINAPI IStorage16_fnOpenStorage(
        if (grfMode & STGM_TRANSACTED)
                FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
        _create_istorage16(ppstg);
-       lpstg = (IStream16Impl*)PTR_SEG_TO_LIN(*ppstg);
+       lpstg = MapSL((SEGPTR)*ppstg);
         DuplicateHandle( GetCurrentProcess(), This->hf, GetCurrentProcess(),
                          &lpstg->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
-       lstrcpyAtoW(name,pwcsName);
+        MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, name, sizeof(name)/sizeof(WCHAR));
        newpps = STORAGE_look_for_named_pps(lpstg->hf,This->stde.pps_dir,name);
        if (newpps==-1) {
                IStream16_fnRelease((IStream16*)lpstg);
@@ -1460,7 +1769,7 @@ HRESULT WINAPI IStorage16_fnOpenStorage(
 HRESULT WINAPI IStorage16_fnOpenStream(
        LPSTORAGE16 iface,LPCOLESTR16 pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream16 **ppstm
 ) {
-       ICOM_THIS(IStorage16Impl,iface);
+       IStorage16Impl *This = (IStorage16Impl *)iface;
        IStream16Impl*  lpstr;
        WCHAR           name[33];
        int             newpps;
@@ -1471,10 +1780,10 @@ HRESULT WINAPI IStorage16_fnOpenStream(
        if (grfMode & STGM_TRANSACTED)
                FIXME("We do not support transacted Compound Storage. Using direct mode.\n");
        _create_istream16(ppstm);
-       lpstr = (IStream16Impl*)PTR_SEG_TO_LIN(*ppstm);
+       lpstr = MapSL((SEGPTR)*ppstm);
         DuplicateHandle( GetCurrentProcess(), This->hf, GetCurrentProcess(),
                          &lpstr->hf, 0, TRUE, DUPLICATE_SAME_ACCESS );
-       lstrcpyAtoW(name,pwcsName);
+        MultiByteToWideChar( CP_ACP, 0, pwcsName, -1, name, sizeof(name)/sizeof(WCHAR));
        newpps = STORAGE_look_for_named_pps(lpstr->hf,This->stde.pps_dir,name);
        if (newpps==-1) {
                IStream16_fnRelease((IStream16*)lpstr);
@@ -1485,8 +1794,8 @@ HRESULT WINAPI IStorage16_fnOpenStream(
                IStream16_fnRelease((IStream16*)lpstr);
                return E_FAIL;
        }
-       lpstr->offset.s.LowPart = 0;
-       lpstr->offset.s.HighPart        = 0;
+       lpstr->offset.u.LowPart = 0;
+       lpstr->offset.u.HighPart        = 0;
        lpstr->ppsent           = newpps;
        return S_OK;
 }
@@ -1497,10 +1806,10 @@ HRESULT WINAPI IStorage16_fnOpenStream(
 static void _create_istorage16(LPSTORAGE16 *stg) {
        IStorage16Impl* lpst;
 
-       if (!stvt16.fnQueryInterface) {
+       if (!stvt16.QueryInterface) {
                HMODULE16       wp = GetModuleHandle16("STORAGE");
                if (wp>=32) {
-#define VTENT(xfn)  stvt16.fn##xfn = (void*)GetProcAddress16(wp,"IStorage16_"#xfn);
+#define VTENT(xfn)  stvt16.xfn = (void*)GetProcAddress16(wp,"IStorage16_"#xfn);
                        VTENT(QueryInterface)
                        VTENT(AddRef)
                        VTENT(Release)
@@ -1520,11 +1829,9 @@ static void _create_istorage16(LPSTORAGE16 *stg) {
                        VTENT(SetStateBits)
                        VTENT(Stat)
 #undef VTENT
-                       segstvt16 = SEGPTR_NEW(ICOM_VTABLE(IStorage16));
-                       memcpy(segstvt16,&stvt16,sizeof(stvt16));
-                       segstvt16 = (ICOM_VTABLE(IStorage16)*)SEGPTR_GET(segstvt16);
+                       segstvt16 = (const IStorage16Vtbl*)MapLS( &stvt16 );
                } else {
-#define VTENT(xfn) stvt16.fn##xfn = IStorage16_fn##xfn;
+#define VTENT(xfn) stvt16.xfn = IStorage16_fn##xfn;
                        VTENT(QueryInterface)
                        VTENT(AddRef)
                        VTENT(Release)
@@ -1549,10 +1856,10 @@ static void _create_istorage16(LPSTORAGE16 *stg) {
                        segstvt16 = &stvt16;
                }
        }
-       lpst = SEGPTR_NEW(IStorage16Impl);
-       ICOM_VTBL(lpst) = segstvt16;
+       lpst = HeapAlloc( GetProcessHeap(), 0, sizeof(*lpst) );
+       lpst->lpVtbl    = segstvt16;
        lpst->ref       = 1;
-       lpst->thisptr   = SEGPTR_GET(lpst);
+       lpst->thisptr   = MapLS(lpst);
        *stg = (void*)lpst->thisptr;
 }
 
@@ -1561,12 +1868,12 @@ static void _create_istorage16(LPSTORAGE16 *stg) {
  */
 
 /******************************************************************************
- *             StgCreateDocFile16      [STORAGE.1]
+ *             StgCreateDocFile      [STORAGE.1]
  */
 HRESULT WINAPI StgCreateDocFile16(
        LPCOLESTR16 pwcsName,DWORD grfMode,DWORD reserved,IStorage16 **ppstgOpen
 ) {
-       HFILE           hf;
+       HANDLE          hf;
        int             i,ret;
        IStorage16Impl* lpstg;
        struct storage_pps_entry        stde;
@@ -1580,9 +1887,9 @@ HRESULT WINAPI StgCreateDocFile16(
                WARN("couldn't open file for storage:%ld\n",GetLastError());
                return E_FAIL;
        }
-       lpstg = (IStorage16Impl*)PTR_SEG_TO_LIN(*ppstgOpen);
+       lpstg = MapSL((SEGPTR)*ppstgOpen);
        lpstg->hf = hf;
-       /* FIXME: check for existance before overwriting? */
+       /* FIXME: check for existence before overwriting? */
        if (!STORAGE_init_storage(hf)) {
                CloseHandle(hf);
                return E_FAIL;
@@ -1606,64 +1913,27 @@ HRESULT WINAPI StgCreateDocFile16(
 }
 
 /******************************************************************************
- * StgIsStorageFile16 [STORAGE.5]
+ * StgIsStorageFile [STORAGE.5]
  */
 HRESULT WINAPI StgIsStorageFile16(LPCOLESTR16 fn) {
-       HFILE           hf;
-       OFSTRUCT        ofs;
-       BYTE            magic[24];
-
-       TRACE("(\'%s\')\n",fn);
-       hf = OpenFile(fn,&ofs,OF_SHARE_DENY_NONE);
-       if (hf==HFILE_ERROR)
-               return STG_E_FILENOTFOUND;
-       if (24!=_lread(hf,magic,24)) {
-               WARN(" too short\n");
-               _lclose(hf);
-               return S_FALSE;
-       }
-       if (!memcmp(magic,STORAGE_magic,8)) {
-               WARN(" -> YES\n");
-               _lclose(hf);
-               return S_OK;
-       }
-       if (!memcmp(magic,STORAGE_notmagic,8)) {
-               WARN(" -> NO\n");
-               _lclose(hf);
-               return S_FALSE;
-       }
-       if (!memcmp(magic,STORAGE_oldmagic,8)) {
-               WARN(" -> old format\n");
-               _lclose(hf);
-               return STG_E_OLDFORMAT;
-       }
-       WARN(" -> Invalid header.\n");
-       _lclose(hf);
-       return STG_E_INVALIDHEADER;
-}
+       UNICODE_STRING strW;
+       HRESULT ret;
 
-/******************************************************************************
- * StgIsStorageFile [OLE32.146]
- */
-HRESULT WINAPI 
-StgIsStorageFile(LPCOLESTR fn) 
-{
-       LPOLESTR16      xfn = HEAP_strdupWtoA(GetProcessHeap(),0,fn);
-       HRESULT ret = StgIsStorageFile16(xfn);
+       RtlCreateUnicodeStringFromAsciiz(&strW, fn);
+       ret = StgIsStorageFile( strW.Buffer );
+       RtlFreeUnicodeString( &strW );
 
-       HeapFree(GetProcessHeap(),0,xfn);
        return ret;
 }
 
-
 /******************************************************************************
- * StgOpenStorage16 [STORAGE.3]
+ * StgOpenStorage [STORAGE.3]
  */
 HRESULT WINAPI StgOpenStorage16(
        LPCOLESTR16 pwcsName,IStorage16 *pstgPriority,DWORD grfMode,
        SNB16 snbExclude,DWORD reserved, IStorage16 **ppstgOpen
 ) {
-       HFILE           hf;
+       HANDLE          hf;
        int             ret,i;
        IStorage16Impl* lpstg;
        struct storage_pps_entry        stde;
@@ -1677,7 +1947,7 @@ HRESULT WINAPI StgOpenStorage16(
                WARN("Couldn't open file for storage\n");
                return E_FAIL;
        }
-       lpstg = (IStorage16Impl*)PTR_SEG_TO_LIN(*ppstgOpen);
+       lpstg = MapSL((SEGPTR)*ppstgOpen);
        lpstg->hf = hf;
 
        i=0;ret=0;
@@ -1694,7 +1964,68 @@ HRESULT WINAPI StgOpenStorage16(
                return E_FAIL;
        }
        return S_OK;
-       
+
+}
+
+/******************************************************************************
+ *              StgIsStorageILockBytes        [STORAGE.6]
+ *
+ * Determines if the ILockBytes contains a storage object.
+ */
+HRESULT WINAPI StgIsStorageILockBytes16(SEGPTR plkbyt)
+{
+  DWORD args[6];
+  HRESULT hres;
+  HANDLE16 hsig;
+  
+  args[0] = (DWORD)plkbyt;     /* iface */
+  args[1] = args[2] = 0;       /* ULARGE_INTEGER offset */
+  args[3] = (DWORD)K32WOWGlobalAllocLock16( 0, 8, &hsig ); /* sig */
+  args[4] = 8;
+  args[5] = 0;
+
+  if (!K32WOWCallback16Ex(
+      (DWORD)((const ILockBytes16Vtbl*)MapSL(
+                  (SEGPTR)((LPLOCKBYTES16)MapSL(plkbyt))->lpVtbl)
+      )->ReadAt,
+      WCB16_PASCAL,
+      6*sizeof(DWORD),
+      (LPVOID)args,
+      (LPDWORD)&hres
+  )) {
+      ERR("CallTo16 ILockBytes16::ReadAt() failed, hres %lx\n",hres);
+      return hres;
+  }
+  if (memcmp(MapSL(args[3]), STORAGE_magic, sizeof(STORAGE_magic)) == 0) {
+    K32WOWGlobalUnlockFree16(args[3]);
+    return S_OK;
+  }
+  K32WOWGlobalUnlockFree16(args[3]);
+  return S_FALSE;
 }
 
+/******************************************************************************
+ *    StgOpenStorageOnILockBytes    [STORAGE.4]
+ */
+HRESULT WINAPI StgOpenStorageOnILockBytes16(
+      ILockBytes16 *plkbyt,
+      IStorage16 *pstgPriority,
+      DWORD grfMode,
+      SNB16 snbExclude,
+      DWORD reserved,
+      IStorage16 **ppstgOpen)
+{
+  IStorage16Impl*      lpstg;
+
+  if ((plkbyt == 0) || (ppstgOpen == 0))
+    return STG_E_INVALIDPOINTER;
+
+  *ppstgOpen = 0;
 
+  _create_istorage16(ppstgOpen);
+  lpstg = MapSL((SEGPTR)*ppstgOpen);
+
+  /* just teach it to use HANDLE instead of ilockbytes :/ */
+
+  return S_OK;
+}