Hi, Some 16bit OLE work. My testprogram is MS Access 2.0 during DB open. The next step required after these is a 16bit storage implementation which can cope with ILockBytes16. Favorable would be to get rid of the 16bit storage implementation and just use the 32bit one. :/ Ciao, Marcus Changelog: ole2nls.c is a 16bit only. No need to define ICOM macros for 16bit iface IMalloc16. Define and implement HGLOBAL_LockBytes16. Started on StgOpenStorageOnILockBytes. Index: Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/ole32/Makefile.in,v retrieving revision 1.25 diff -u -u -r1.25 Makefile.in --- Makefile.in 3 Jan 2003 19:12:56 -0000 1.25 +++ Makefile.in 4 Jan 2003 09:51:17 -0000 @@ -32,7 +32,6 @@ ole2.c \ ole2stubs.c \ ole2impl.c \ - ole2nls.c \ ole32_main.c \ oleobj.c \ oleproxy.c \ @@ -41,6 +40,8 @@ stg_stream.c \ storage.c \ storage32.c + +C_SRCS16 = ole2nls.c RC_SRCS = ole32res.rc Index: ifs.h =================================================================== RCS file: /home/wine/wine/dlls/ole32/ifs.h,v retrieving revision 1.5 diff -u -u -r1.5 ifs.h --- ifs.h 23 Dec 2002 01:39:35 -0000 1.5 +++ ifs.h 4 Jan 2003 09:51:18 -0000 @@ -41,20 +41,30 @@ ICOM_DEFINE(IMalloc16,IUnknown) #undef ICOM_INTERFACE -/*** IUnknown methods ***/ -#define IMalloc16_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) -#define IMalloc16_AddRef(p) ICOM_CALL (AddRef,p) -#define IMalloc16_Release(p) ICOM_CALL (Release,p) -/*** IMalloc16 methods ***/ -#define IMalloc16_Alloc(p,a) ICOM_CALL1(Alloc,p,a) -#define IMalloc16_Realloc(p,a,b) ICOM_CALL2(Realloc,p,a,b) -#define IMalloc16_Free(p,a) ICOM_CALL1(Free,p,a) -#define IMalloc16_GetSize(p,a) ICOM_CALL1(GetSize,p,a) -#define IMalloc16_DidAlloc(p,a) ICOM_CALL1(DidAlloc,p,a) -#define IMalloc16_HeapMinimize(p) ICOM_CALL (HeapMinimize,p) - /**********************************************************************/ extern LPMALLOC16 IMalloc16_Constructor(); + +/**********************************************************************/ + +typedef struct ILockBytes16 *LPLOCKBYTES16, ILockBytes16; + +#define ICOM_INTERFACE ILockBytes +#define ILockBytes16_METHODS \ + ICOM_METHOD4(HRESULT,ReadAt, ULARGE_INTEGER,ulOffset, void*,pv, ULONG, cb, ULONG*,pcbRead) \ + ICOM_METHOD4(HRESULT,WriteAt, ULARGE_INTEGER,ulOffset, const void*,pv, ULONG,cb, ULONG*,pcbWritten) \ + ICOM_METHOD (HRESULT,Flush) \ + ICOM_METHOD1(HRESULT,SetSize, ULARGE_INTEGER,cb) \ + ICOM_METHOD3(HRESULT,LockRegion, ULARGE_INTEGER,libOffset, ULARGE_INTEGER, cb, DWORD,dwLockType) \ + ICOM_METHOD3(HRESULT,UnlockRegion, ULARGE_INTEGER,libOffset, ULARGE_INTEGER, cb, DWORD,dwLockType) \ + ICOM_METHOD2(HRESULT,Stat, STATSTG*,pstatstg, DWORD,grfStatFlag) + +#define ILockBytes16_IMETHODS \ + IUnknown_IMETHODS \ + ILockBytes16_METHODS + +ICOM_DEFINE(ILockBytes16,IUnknown) +#undef ICOM_INTERFACE + #endif /* __WINE_OLE_IFS_H */ Index: memlockbytes.c =================================================================== RCS file: /home/wine/wine/dlls/ole32/memlockbytes.c,v retrieving revision 1.8 diff -u -u -r1.8 memlockbytes.c --- memlockbytes.c 5 Jul 2002 21:19:55 -0000 1.8 +++ memlockbytes.c 4 Jan 2003 09:51:18 -0000 @@ -21,14 +21,18 @@ #include "config.h" +#include <assert.h> #include <string.h> #include "windef.h" +#include "wine/winbase16.h" #include "objbase.h" #include "ole2.h" #include "winbase.h" #include "winerror.h" +#include "ifs.h" + #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -617,3 +621,544 @@ return S_OK; } + +/****************************************************************************** + * HGLOBALLockBytesImpl16 definition. + * + * This class imlements the ILockBytes inteface and represents a byte array + * object supported by an HGLOBAL pointer. + */ +struct HGLOBALLockBytesImpl16 +{ + /* + * Needs to be the first item in the stuct + * since we want to cast this in an ILockBytes pointer + */ + ICOM_VFIELD(ILockBytes16); + ULONG ref; + + /* + * Support for the LockBytes object + */ + HGLOBAL16 supportHandle; + + /* + * This flag is TRUE if the HGLOBAL is destroyed when the object + * is finally released. + */ + BOOL deleteOnRelease; + /* + * Helper variable that contains the size of the byte array + */ + ULARGE_INTEGER byteArraySize; +}; + +typedef struct HGLOBALLockBytesImpl16 HGLOBALLockBytesImpl16; + +HGLOBALLockBytesImpl16* HGLOBALLockBytesImpl16_Construct( + HGLOBAL16 hGlobal, + BOOL16 fDeleteOnRelease); + +void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This); + +HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface( + ILockBytes16* iface, + REFIID riid, /* [in] */ + void** ppvObject); /* [iid_is][out] */ + +ULONG WINAPI HGLOBALLockBytesImpl16_AddRef( + ILockBytes16* iface); + +ULONG WINAPI HGLOBALLockBytesImpl16_Release( + ILockBytes16* iface); + +HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead); /* [out] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten); /* [out] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_Flush( + ILockBytes16* iface); + +HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize( + ILockBytes16* iface, + ULARGE_INTEGER libNewSize); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_Stat( + ILockBytes16* iface, + STATSTG16* pstatstg, /* [out] */ + DWORD grfStatFlag); /* [in] */ + +/****************************************************************************** + * + * HGLOBALLockBytesImpl16 implementation + * + */ + +/****************************************************************************** + * This is the constructor for the HGLOBALLockBytesImpl16 class. + * + * Params: + * hGlobal - Handle that will support the stream. can be NULL. + * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL16 will be released + * when the IStream object is destroyed. + */ +HGLOBALLockBytesImpl16* +HGLOBALLockBytesImpl16_Construct(HGLOBAL16 hGlobal, + BOOL16 fDeleteOnRelease) +{ + HGLOBALLockBytesImpl16* newLockBytes; + + static ICOM_VTABLE(ILockBytes16) vt16; + static SEGPTR msegvt16; + HMODULE16 hcomp = GetModuleHandle16("OLE2"); + + + TRACE("(%x,%d)\n",hGlobal,fDeleteOnRelease); + newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl16)); + if (newLockBytes == NULL) + return NULL; + + /* + * Set up the virtual function table and reference count. + */ + if (!msegvt16) + { +#define VTENT(x) vt16.x = (void*)GetProcAddress16(hcomp,"HGLOBALLockBytesImpl16_"#x);assert(vt16.x) + VTENT(QueryInterface); + VTENT(AddRef); + VTENT(Release); + VTENT(ReadAt); + VTENT(WriteAt); + VTENT(Flush); + VTENT(SetSize); + VTENT(LockRegion); + VTENT(UnlockRegion); +#undef VTENT + msegvt16 = MapLS( &vt16 ); + } + ICOM_VTBL(newLockBytes) = (ICOM_VTABLE(ILockBytes16)*)msegvt16; + newLockBytes->ref = 0; + /* + * Initialize the support. + */ + newLockBytes->supportHandle = hGlobal; + newLockBytes->deleteOnRelease = fDeleteOnRelease; + + /* + * This method will allocate a handle if one is not supplied. + */ + if (newLockBytes->supportHandle == 0) + newLockBytes->supportHandle = GlobalAlloc16(GMEM_MOVEABLE | GMEM_NODISCARD, 0); + + /* + * Initialize the size of the array to the size of the handle. + */ + newLockBytes->byteArraySize.s.HighPart = 0; + newLockBytes->byteArraySize.s.LowPart = GlobalSize16( + newLockBytes->supportHandle); + + return (HGLOBALLockBytesImpl16*)MapLS(newLockBytes); +} + +/****************************************************************************** + * This is the destructor of the HGLOBALStreamImpl class. + * + * This method will clean-up all the resources used-up by the given + * HGLOBALLockBytesImpl16 class. The pointer passed-in to this function will be + * freed and will not be valid anymore. + */ +void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This) +{ + TRACE("()\n"); + /* + * Release the HGlobal if the constructor asked for that. + */ + if (This->deleteOnRelease) + { + GlobalFree16(This->supportHandle); + This->supportHandle = 0; + } + + /* + * Finally, free the memory used-up by the class. + */ + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** + * This implements the IUnknown method QueryInterface for this + * class + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface( + ILockBytes16* iface, /* [in] SEGPTR */ + REFIID riid, /* [in] */ + void** ppvObject) /* [iid_is][out] (ptr to SEGPTR!) */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)MapSL((SEGPTR)iface); + + TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject); + /* + * Perform a sanity check on the parameters. + */ + if (ppvObject==0) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if ( !memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) || + !memcmp(&IID_ILockBytes, riid, sizeof(IID_ILockBytes)) + ) + *ppvObject = (void*)iface; + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* + * Query Interface always increases the reference count by one when it is + * successful + */ + HGLOBALLockBytesImpl16_AddRef((ILockBytes16*)This); + + return S_OK; +} + +/****************************************************************************** + * This implements the IUnknown method AddRef for this + * class + */ +ULONG WINAPI HGLOBALLockBytesImpl16_AddRef(ILockBytes16* iface) +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + TRACE("(%p)\n",This); + + This->ref++; + + return This->ref; +} + +/****************************************************************************** + * This implements the IUnknown method Release for this + * class + */ +ULONG WINAPI HGLOBALLockBytesImpl16_Release(ILockBytes16* iface) +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + ULONG newRef; + TRACE("(%p)\n",This); + + This->ref--; + + newRef = This->ref; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (newRef==0) + HGLOBALLockBytesImpl16_Destroy(This); + return newRef; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It reads a block of information from the byte array at the specified + * offset. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead) /* [out] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + void* supportBuffer; + ULONG bytesReadBuffer = 0; + ULONG bytesToReadFromBuffer; + + TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbRead); + /* + * If the caller is not interested in the number of bytes read, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbRead == 0) + pcbRead = &bytesReadBuffer; + + /* + * Make sure the offset is valid. + */ + if (ulOffset.s.LowPart > This->byteArraySize.s.LowPart) + return E_FAIL; + + /* + * Using the known size of the array, calculate the number of bytes + * to read. + */ + bytesToReadFromBuffer = min(This->byteArraySize.s.LowPart - + ulOffset.s.LowPart, cb); + + /* + * Lock the buffer in position and copy the data. + */ + supportBuffer = GlobalLock16(This->supportHandle); + + memcpy(pv, + (char *) supportBuffer + ulOffset.s.LowPart, + bytesToReadFromBuffer); + + /* + * Return the number of bytes read. + */ + *pcbRead = bytesToReadFromBuffer; + + /* + * Cleanup + */ + GlobalUnlock16(This->supportHandle); + + /* + * The function returns S_OK if the specified number of bytes were read + * or the end of the array was reached. + * It returns STG_E_READFAULT if the number of bytes to read does not equal + * the number of bytes actually read. + */ + if(*pcbRead == cb) + return S_OK; + + return STG_E_READFAULT; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It writes the specified bytes at the specified offset. + * position. If the array is too small, it will be resized. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten) /* [out] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + void* supportBuffer; + ULARGE_INTEGER newSize; + ULONG bytesWritten = 0; + + TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbWritten); + /* + * If the caller is not interested in the number of bytes written, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbWritten == 0) + pcbWritten = &bytesWritten; + + if (cb == 0) + return S_OK; + + newSize.s.HighPart = 0; + newSize.s.LowPart = ulOffset.s.LowPart + cb; + + /* + * Verify if we need to grow the stream + */ + if (newSize.s.LowPart > This->byteArraySize.s.LowPart) + { + /* grow stream */ + if (HGLOBALLockBytesImpl16_SetSize(iface, newSize) == STG_E_MEDIUMFULL) + return STG_E_MEDIUMFULL; + } + + /* + * Lock the buffer in position and copy the data. + */ + supportBuffer = GlobalLock16(This->supportHandle); + + memcpy((char *) supportBuffer + ulOffset.s.LowPart, pv, cb); + + /* + * Return the number of bytes written. + */ + *pcbWritten = cb; + + /* + * Cleanup + */ + GlobalUnlock16(This->supportHandle); + + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_Flush(ILockBytes16* iface) +{ + TRACE("(%p)\n",iface); + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It will change the size of the byte array. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize( + ILockBytes16* iface, + ULARGE_INTEGER libNewSize) /* [in] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + TRACE("(%p,%ld)\n",This,libNewSize.s.LowPart); + /* + * As documented. + */ + if (libNewSize.s.HighPart != 0) + return STG_E_INVALIDFUNCTION; + + if (This->byteArraySize.s.LowPart == libNewSize.s.LowPart) + return S_OK; + + /* + * Re allocate the HGlobal to fit the new size of the stream. + */ + This->supportHandle = GlobalReAlloc16(This->supportHandle, + libNewSize.s.LowPart, + 0); + + if (This->supportHandle == 0) + return STG_E_MEDIUMFULL; + + This->byteArraySize.s.LowPart = libNewSize.s.LowPart; + + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * The global memory implementation of ILockBytes does not support locking. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + return STG_E_INVALIDFUNCTION; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * The global memory implementation of ILockBytes does not support locking. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + return STG_E_INVALIDFUNCTION; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * This method returns information about the current + * byte array object. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_Stat( + ILockBytes16*iface, + STATSTG16* pstatstg, /* [out] */ + DWORD grfStatFlag) /* [in] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + memset(pstatstg, 0, sizeof(STATSTG16)); + + pstatstg->pwcsName = NULL; + pstatstg->type = STGTY_LOCKBYTES; + pstatstg->cbSize = This->byteArraySize; + + return S_OK; +} + +/****************************************************************************** + * CreateILockBytesOnHGlobal [OLE2.54] + * + * Creates an ILockBytes interface for a HGLOBAL handle. + * + * Params: + * hGlobal the global handle (16bit) + * fDeleteOnRelease delete handle on release. + * ppLkbyt pointer to ILockBytes interface. + * + * Returns: + * Staddard OLE error return codes. + * + */ +HRESULT WINAPI CreateILockBytesOnHGlobal16(HGLOBAL16 hGlobal, + BOOL16 fDeleteOnRelease, + /*SEGPTR**/ LPLOCKBYTES16* ppLkbyt) +{ + HGLOBALLockBytesImpl16* newLockBytes; /* SEGPTR */ + + newLockBytes = HGLOBALLockBytesImpl16_Construct(hGlobal, fDeleteOnRelease); + + if (newLockBytes != NULL) + return HGLOBALLockBytesImpl16_QueryInterface((ILockBytes16*)newLockBytes, + &IID_ILockBytes, + (void**)ppLkbyt); + return E_OUTOFMEMORY; +} + Index: ole2.spec =================================================================== RCS file: /home/wine/wine/dlls/ole32/ole2.spec,v retrieving revision 1.4 diff -u -u -r1.4 ole2.spec --- ole2.spec 21 Jun 2002 19:15:48 -0000 1.4 +++ ole2.spec 4 Jan 2003 09:51:19 -0000 @@ -51,7 +51,7 @@ 51 stub OLEDUPLICATEDATA 52 stub OLEGETICONOFFILE 53 stub OLEGETICONOFCLASS -54 stub CREATEILOCKBYTESONHGLOBAL +54 pascal CreateILockBytesOnHGLOBAL(word word ptr) CreateILockBytesOnHGlobal16 55 stub GETHGLOBALFROMILOCKBYTES 56 pascal16 OleMetaFilePictFromIconAndLabel(word str str word) OleMetaFilePictFromIconAndLabel16 57 stub GETCLASSFILE @@ -144,3 +144,15 @@ 159 stub _IID_IOLECACHE2 160 stub _IID_IOLECACHECONTROL 161 stub _IID_IRUNNABLEOBJECT + +# WINE MemLockBytes implementation. +500 cdecl HGLOBALLockBytesImpl16_QueryInterface(segptr ptr ptr) HGLOBALLockBytesImpl16_QueryInterface +501 cdecl HGLOBALLockBytesImpl16_AddRef(ptr) HGLOBALLockBytesImpl16_AddRef +502 cdecl HGLOBALLockBytesImpl16_Release(ptr) HGLOBALLockBytesImpl16_Release +503 cdecl HGLOBALLockBytesImpl16_ReadAt(ptr long long ptr ptr) HGLOBALLockBytesImpl16_ReadAt +504 cdecl HGLOBALLockBytesImpl16_WriteAt(ptr long long ptr long ptr) HGLOBALLockBytesImpl16_WriteAt +505 cdecl HGLOBALLockBytesImpl16_Flush(ptr) HGLOBALLockBytesImpl16_Flush +506 cdecl HGLOBALLockBytesImpl16_SetSize(ptr long long) HGLOBALLockBytesImpl16_SetSize +507 cdecl HGLOBALLockBytesImpl16_LockRegion(ptr long long long long long) HGLOBALLockBytesImpl16_LockRegion +508 cdecl HGLOBALLockBytesImpl16_UnlockRegion(ptr long long long long long) HGLOBALLockBytesImpl16_UnlockRegion +509 cdecl HGLOBALLockBytesImpl16_Stat(ptr ptr long) HGLOBALLockBytesImpl16_Stat Index: storage.c =================================================================== RCS file: /home/wine/wine/dlls/ole32/storage.c,v retrieving revision 1.28 diff -u -u -r1.28 storage.c --- storage.c 5 Dec 2002 20:33:08 -0000 1.28 +++ storage.c 4 Jan 2003 09:51:19 -0000 @@ -34,10 +34,13 @@ #include "winternl.h" #include "winerror.h" #include "wine/winbase16.h" +#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); @@ -1690,4 +1693,67 @@ } 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)((ICOM_VTABLE(ILockBytes16)*)MapSL( + (SEGPTR)ICOM_VTBL(((LPLOCKBYTES16)MapSL(plkbyt)))) + )->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; } Index: storage.spec =================================================================== RCS file: /home/wine/wine/dlls/ole32/storage.spec,v retrieving revision 1.4 diff -u -u -r1.4 storage.spec --- storage.spec 21 Jun 2002 19:15:48 -0000 1.4 +++ storage.spec 4 Jan 2003 09:51:19 -0000 @@ -4,10 +4,11 @@ 1 pascal StgCreateDocFileA(str long long ptr) StgCreateDocFile16 2 stub StgCreateDocFileOnILockBytes +# 2 pascal StgCreateDocFileOnILockBytes(ptr long long ptr) StgCreateDocFileOnILockBytes16 3 pascal StgOpenStorage(str ptr long ptr long ptr) StgOpenStorage16 -4 stub StgOpenStorageOnILockBytes +4 pascal StgOpenStorageOnILockBytes(ptr ptr long long long ptr) StgOpenStorageOnILockBytes16 5 pascal StgIsStorageFile(str) StgIsStorageFile16 -6 stub StgIsStorageILockBytes +6 pascal StgIsStorageILockBytes(segptr) StgIsStorageILockBytes16 7 stub StgSetTimes #8 WEP #9 ___EXPORTEDSTUB