inetcomm: Add an implementation of IVirtualStream.
Hans Leidekker
hans at codeweavers.com
Fri Nov 7 06:37:19 CST 2008
This interface is undocumented but fortunately its name was enough
of a hint to create a sensible implementation. Used by Outlook when
retrieving or sending a mail.
-Hans
diff --git a/dlls/inetcomm/inetcomm_main.c b/dlls/inetcomm/inetcomm_main.c
index 1d71877..22f1919 100644
--- a/dlls/inetcomm/inetcomm_main.c
+++ b/dlls/inetcomm/inetcomm_main.c
@@ -139,6 +139,7 @@ static cf mime_body_cf = { &cf_vtbl, MimeBody_create };
static cf mime_allocator_cf = { &cf_vtbl, MimeAllocator_create };
static cf mime_message_cf = { &cf_vtbl, MimeMessage_create };
static cf mime_security_cf = { &cf_vtbl, MimeSecurity_create };
+static cf virtual_stream_cf = { &cf_vtbl, VirtualStream_create };
/***********************************************************************
* DllGetClassObject (INETCOMM.@)
@@ -177,6 +178,10 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
{
cf = (IClassFactory*) &mime_allocator_cf.lpVtbl;
}
+ else if( IsEqualCLSID( rclsid, &CLSID_IVirtualStream ))
+ {
+ cf = (IClassFactory*) &virtual_stream_cf.lpVtbl;
+ }
if ( !cf )
{
diff --git a/dlls/inetcomm/inetcomm_private.h b/dlls/inetcomm/inetcomm_private.h
index 589f92c..036113c 100644
--- a/dlls/inetcomm/inetcomm_private.h
+++ b/dlls/inetcomm/inetcomm_private.h
@@ -78,6 +78,8 @@ HRESULT MimeAllocator_create(IUnknown *outer, void **obj);
HRESULT MimeMessage_create(IUnknown *outer, void **obj);
HRESULT MimeSecurity_create(IUnknown *outer, void **obj);
+HRESULT VirtualStream_create(IUnknown *outer, void **obj);
+
HRESULT MimeInternational_Construct(IMimeInternational **internat);
HRESULT SMTPTransportCF_Create(REFIID riid, LPVOID *ppv);
diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c
index 07aa6bd..7b4e4b8 100644
--- a/dlls/inetcomm/mimeole.c
+++ b/dlls/inetcomm/mimeole.c
@@ -2989,3 +2989,304 @@ HRESULT WINAPI MimeOleGetAllocator(IMimeAllocator **alloc)
{
return MimeAllocator_create(NULL, (void**)alloc);
}
+
+typedef struct
+{
+ IStreamVtbl *lpVtbl;
+ LONG refs;
+
+ char *buffer;
+ ULARGE_INTEGER size, allocated, pos;
+} virtual_stream_t;
+
+static HRESULT WINAPI virtual_stream_QueryInterface(
+ IStream* iface,
+ REFIID riid,
+ void **ppvObject)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
+ *ppvObject = NULL;
+
+ if(IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISequentialStream) ||
+ IsEqualIID(riid, &IID_IStream) ||
+ IsEqualIID(riid, &IID_IVirtualStream))
+ {
+ IStream_AddRef(iface);
+ *ppvObject = iface;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI virtual_stream_AddRef(
+ IStream* iface)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+
+ TRACE("(%p)\n", This);
+ return InterlockedIncrement(&This->refs);
+}
+
+static ULONG WINAPI virtual_stream_Release(
+ IStream* iface)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+ LONG refs;
+
+ TRACE("(%p)\n", This);
+
+ refs = InterlockedDecrement(&This->refs);
+ if (!refs)
+ {
+ HeapFree(GetProcessHeap(), 0, This->buffer);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return refs;
+}
+
+static HRESULT WINAPI virtual_stream_Read(
+ IStream* iface,
+ void *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+
+ TRACE("(%p, %d, %p)\n", pv, cb, pcbRead);
+
+ if (This->pos.QuadPart + cb > This->size.QuadPart)
+ cb = This->size.QuadPart - This->pos.QuadPart;
+
+ memcpy(pv, This->buffer + This->pos.QuadPart, cb);
+ if (pcbRead) *pcbRead = cb;
+ This->pos.QuadPart += cb;
+ return S_OK;
+}
+
+#define INITIAL_BUFFER_SIZE 4096
+
+static HRESULT WINAPI virtual_stream_Write(
+ IStream* iface,
+ const void *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+ ULARGE_INTEGER size;
+
+ TRACE("(%p, %d, %p)\n", pv, cb, pcbWritten);
+
+ if (!This->buffer)
+ {
+ size.QuadPart = max(cb, INITIAL_BUFFER_SIZE);
+ This->buffer = HeapAlloc(GetProcessHeap(), 0, size.QuadPart);
+ if (!This->buffer) return E_OUTOFMEMORY;
+ This->allocated.QuadPart = size.QuadPart;
+ }
+ while (cb > This->allocated.QuadPart - This->pos.QuadPart)
+ {
+ size.QuadPart = This->allocated.QuadPart * 2;
+ This->buffer = HeapReAlloc(GetProcessHeap(), 0, This->buffer, size.QuadPart);
+ if (!This->buffer) return E_OUTOFMEMORY;
+ This->allocated.QuadPart = size.QuadPart;
+ }
+ memcpy(This->buffer + This->pos.QuadPart, pv, cb);
+ if (pcbWritten) *pcbWritten = cb;
+ This->pos.QuadPart += cb;
+ return S_OK;
+}
+
+static HRESULT WINAPI virtual_stream_Seek(
+ IStream* iface,
+ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+ LARGE_INTEGER new_pos;
+
+ TRACE("(%08x.%08x, %x, %p)\n", dlibMove.u.HighPart, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
+
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ new_pos = dlibMove;
+ break;
+ case STREAM_SEEK_CUR:
+ new_pos.QuadPart = This->pos.QuadPart + dlibMove.QuadPart;
+ break;
+ case STREAM_SEEK_END:
+ new_pos.QuadPart = This->size.QuadPart + dlibMove.QuadPart;
+ break;
+ default:
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ if (new_pos.QuadPart < 0) new_pos.QuadPart = 0;
+ else if (new_pos.QuadPart > This->size.QuadPart) new_pos.QuadPart = This->size.QuadPart;
+
+ This->pos.QuadPart = new_pos.QuadPart;
+
+ if (plibNewPosition) *plibNewPosition = This->pos;
+ return S_OK;
+}
+
+static HRESULT WINAPI virtual_stream_SetSize(
+ IStream* iface,
+ ULARGE_INTEGER libNewSize)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+
+ TRACE("(%08x.%08x)\n", libNewSize.u.HighPart, libNewSize.u.LowPart);
+
+ This->size.QuadPart = libNewSize.QuadPart;
+ return S_OK;
+}
+
+static HRESULT WINAPI virtual_stream_CopyTo(
+ IStream *iface,
+ IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ virtual_stream_t *This = (virtual_stream_t *)iface;
+ HRESULT hr = S_OK;
+ BYTE buffer[256];
+ ULONG bytes_read, bytes_written, copy_size;
+ ULARGE_INTEGER total_read;
+ ULARGE_INTEGER total_written;
+
+ TRACE("(%p, %08x.%08x, %p, %p)\n", pstm, cb.u.HighPart, cb.u.LowPart, pcbRead, pcbWritten);
+
+ total_read.QuadPart = 0;
+ total_written.QuadPart = 0;
+
+ if (cb.QuadPart == -1) cb.QuadPart = This->size.QuadPart;
+ while (cb.QuadPart > 0)
+ {
+ if (cb.QuadPart >= sizeof(buffer))
+ copy_size = sizeof(buffer);
+ else
+ copy_size = cb.u.LowPart;
+
+ hr = virtual_stream_Read(iface, buffer, copy_size, &bytes_read);
+ if (FAILED(hr)) break;
+
+ total_read.QuadPart += bytes_read;
+ if (bytes_read)
+ {
+ hr = IStream_Write(pstm, buffer, bytes_read, &bytes_written);
+ if (FAILED(hr)) break;
+ total_written.QuadPart += bytes_written;
+ }
+
+ if (bytes_read != copy_size)
+ cb.QuadPart = 0;
+ else
+ cb.QuadPart -= bytes_read;
+ }
+
+ if (pcbRead) pcbRead->QuadPart = total_read.QuadPart;
+ if (pcbWritten) pcbWritten->QuadPart = total_written.QuadPart;
+
+ return hr;
+}
+
+static HRESULT WINAPI virtual_stream_Commit(
+ IStream* iface,
+ DWORD grfCommitFlags)
+{
+ TRACE("(%08x)\n", grfCommitFlags);
+ return S_OK;
+}
+
+static HRESULT WINAPI virtual_stream_Revert(
+ IStream* iface)
+{
+ FIXME("()\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI virtual_stream_LockRegion(
+ IStream* iface,
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ FIXME("(%08x.%08x, %08x.%08x, %08x)\n", libOffset.u.HighPart, libOffset.u.LowPart,
+ cb.u.HighPart, cb.u.LowPart, dwLockType);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI virtual_stream_UnlockRegion(
+ IStream* iface,
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ FIXME("(%08x.%08x, %08x.%08x, %08x)\n", libOffset.u.HighPart, libOffset.u.LowPart,
+ cb.u.HighPart, cb.u.LowPart, dwLockType);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI virtual_stream_Stat(
+ IStream* iface,
+ STATSTG *pstatstg,
+ DWORD grfStatFlag)
+{
+ FIXME("(%p, %08x)\n", pstatstg, grfStatFlag);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI virtual_stream_Clone(
+ IStream* iface,
+ IStream **ppstm)
+{
+ FIXME("(%p)\n", ppstm);
+ return E_NOTIMPL;
+}
+
+static struct IStreamVtbl virtual_stream_vtbl =
+{
+ virtual_stream_QueryInterface,
+ virtual_stream_AddRef,
+ virtual_stream_Release,
+ virtual_stream_Read,
+ virtual_stream_Write,
+ virtual_stream_Seek,
+ virtual_stream_SetSize,
+ virtual_stream_CopyTo,
+ virtual_stream_Commit,
+ virtual_stream_Revert,
+ virtual_stream_LockRegion,
+ virtual_stream_UnlockRegion,
+ virtual_stream_Stat,
+ virtual_stream_Clone
+};
+
+HRESULT VirtualStream_create(IUnknown *outer, void **obj)
+{
+ virtual_stream_t *This;
+
+ TRACE("(%p, %p)\n", outer, obj);
+
+ *obj = NULL;
+ if (outer) return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+ if(!This) return E_OUTOFMEMORY;
+
+ This->lpVtbl = &virtual_stream_vtbl;
+ This->refs = 1;
+ This->buffer = NULL;
+ This->allocated.QuadPart = 0;
+ This->size.QuadPart = 0;
+ This->pos.QuadPart = 0;
+
+ *obj = (IStream*)&This->lpVtbl;
+ return S_OK;
+}
diff --git a/dlls/inetcomm/regsvr.c b/dlls/inetcomm/regsvr.c
index 4c7310c..8ac982e 100644
--- a/dlls/inetcomm/regsvr.c
+++ b/dlls/inetcomm/regsvr.c
@@ -464,6 +464,12 @@ static struct regsvr_coclass const coclass_list[] = {
"inetcomm.dll",
"Both"
},
+ { &CLSID_IVirtualStream,
+ "CLSID_IVirtualStream",
+ NULL,
+ "inetcomm.dll",
+ "Both"
+ },
{ NULL } /* list terminator */
};
diff --git a/include/mimeole.idl b/include/mimeole.idl
index d74cdb5..2e7f5d6 100644
--- a/include/mimeole.idl
+++ b/include/mimeole.idl
@@ -34,6 +34,7 @@ cpp_quote("DEFINE_GUID(CLSID_IMimeAllocator, 0xfd853cdd, 0x7f86, 0x11d0, 0x82, 0
cpp_quote("DEFINE_GUID(CLSID_IMimeMessage, 0xfd853ce3, 0x7f86, 0x11d0, 0x82, 0x52, 0x0, 0xc0, 0x4f, 0xd8, 0x5a, 0xb4);")
cpp_quote("DEFINE_GUID(CLSID_IMimeSecurity, 0xfd853cde, 0x7f86, 0x11d0, 0x82, 0x52, 0x0, 0xc0, 0x4f, 0xd8, 0x5a, 0xb4);")
cpp_quote("DEFINE_GUID(CLSID_IVirtualStream, 0xfd853cdf, 0x7f86, 0x11d0, 0x82, 0x52, 0x0, 0xc0, 0x4f, 0xd8, 0x5a, 0xb4);")
+cpp_quote("DEFINE_GUID(IID_IVirtualStream, 0xc5588359, 0x7f86, 0x11d0, 0x82, 0x52, 0x0, 0xc0, 0x4f, 0xd8, 0x5a, 0xb4);")
cpp_quote("#define MIME_E_REG_CREATE_KEY 0x800cce01")
cpp_quote("#define MIME_E_REG_QUERY_INFO 0x800cce02")
More information about the wine-patches
mailing list