shcore: Implement SHCreateMemStream().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d84de4ca00
commit
b54d72ef0b
|
@ -28,7 +28,9 @@
|
||||||
#include "initguid.h"
|
#include "initguid.h"
|
||||||
#include "ocidl.h"
|
#include "ocidl.h"
|
||||||
#include "shellscalingapi.h"
|
#include "shellscalingapi.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/heap.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shcore);
|
WINE_DEFAULT_DEBUG_CHANNEL(shcore);
|
||||||
|
@ -492,3 +494,309 @@ WCHAR** WINAPI CommandLineToArgvW(const WCHAR *cmdline, int *numargs)
|
||||||
|
|
||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct shstream
|
||||||
|
{
|
||||||
|
IStream IStream_iface;
|
||||||
|
LONG refcount;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
BYTE *buffer;
|
||||||
|
DWORD length;
|
||||||
|
DWORD position;
|
||||||
|
} mem;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct shstream *impl_from_IStream(IStream *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, struct shstream, IStream_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_QueryInterface(IStream *iface, REFIID riid, void **out)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)->(%s, %p)\n", stream, debugstr_guid(riid), out);
|
||||||
|
|
||||||
|
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IStream))
|
||||||
|
{
|
||||||
|
*out = iface;
|
||||||
|
IStream_AddRef(iface);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI shstream_AddRef(IStream *iface)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
ULONG refcount = InterlockedIncrement(&stream->refcount);
|
||||||
|
|
||||||
|
TRACE("(%p)->(%u)\n", stream, refcount);
|
||||||
|
|
||||||
|
return refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI memstream_Release(IStream *iface)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
ULONG refcount = InterlockedDecrement(&stream->refcount);
|
||||||
|
|
||||||
|
TRACE("(%p)->(%u)\n", stream, refcount);
|
||||||
|
|
||||||
|
if (!refcount)
|
||||||
|
{
|
||||||
|
heap_free(stream->u.mem.buffer);
|
||||||
|
heap_free(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI memstream_Read(IStream *iface, void *buff, ULONG buff_size, ULONG *read_len)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
DWORD length;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%p, %u, %p)\n", stream, buff, buff_size, read_len);
|
||||||
|
|
||||||
|
if (stream->u.mem.position >= stream->u.mem.length)
|
||||||
|
length = 0;
|
||||||
|
else
|
||||||
|
length = stream->u.mem.length - stream->u.mem.position;
|
||||||
|
|
||||||
|
length = buff_size > length ? length : buff_size;
|
||||||
|
if (length != 0) /* not at end of buffer and we want to read something */
|
||||||
|
{
|
||||||
|
memmove(buff, stream->u.mem.buffer + stream->u.mem.position, length);
|
||||||
|
stream->u.mem.position += length; /* adjust pointer */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_len)
|
||||||
|
*read_len = length;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI memstream_Write(IStream *iface, const void *buff, ULONG buff_size, ULONG *written)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
DWORD length = stream->u.mem.position + buff_size;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%p, %u, %p)\n", stream, buff, buff_size, written);
|
||||||
|
|
||||||
|
if (length < stream->u.mem.position) /* overflow */
|
||||||
|
return STG_E_INSUFFICIENTMEMORY;
|
||||||
|
|
||||||
|
if (length > stream->u.mem.length)
|
||||||
|
{
|
||||||
|
BYTE *buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stream->u.mem.buffer, length);
|
||||||
|
if (!buffer)
|
||||||
|
return STG_E_INSUFFICIENTMEMORY;
|
||||||
|
|
||||||
|
stream->u.mem.length = length;
|
||||||
|
stream->u.mem.buffer = buffer;
|
||||||
|
}
|
||||||
|
memmove(stream->u.mem.buffer + stream->u.mem.position, buff, buff_size);
|
||||||
|
stream->u.mem.position += buff_size; /* adjust pointer */
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
*written = buff_size;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI memstream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER*new_pos)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
LARGE_INTEGER tmp;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%s, %d, %p)\n", stream, wine_dbgstr_longlong(move.QuadPart), origin, new_pos);
|
||||||
|
|
||||||
|
if (origin == STREAM_SEEK_SET)
|
||||||
|
tmp = move;
|
||||||
|
else if (origin == STREAM_SEEK_CUR)
|
||||||
|
tmp.QuadPart = stream->u.mem.position + move.QuadPart;
|
||||||
|
else if (origin == STREAM_SEEK_END)
|
||||||
|
tmp.QuadPart = stream->u.mem.length + move.QuadPart;
|
||||||
|
else
|
||||||
|
return STG_E_INVALIDPARAMETER;
|
||||||
|
|
||||||
|
if (tmp.QuadPart < 0)
|
||||||
|
return STG_E_INVALIDFUNCTION;
|
||||||
|
|
||||||
|
/* we cut off the high part here */
|
||||||
|
stream->u.mem.position = tmp.u.LowPart;
|
||||||
|
|
||||||
|
if (new_pos)
|
||||||
|
new_pos->QuadPart = stream->u.mem.position;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI memstream_SetSize(IStream *iface, ULARGE_INTEGER new_size)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
DWORD length;
|
||||||
|
BYTE *buffer;
|
||||||
|
|
||||||
|
TRACE("(%p, %s)\n", stream, wine_dbgstr_longlong(new_size.QuadPart));
|
||||||
|
|
||||||
|
/* we cut off the high part here */
|
||||||
|
length = new_size.u.LowPart;
|
||||||
|
buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stream->u.mem.buffer, length);
|
||||||
|
if (!buffer)
|
||||||
|
return STG_E_INSUFFICIENTMEMORY;
|
||||||
|
|
||||||
|
stream->u.mem.buffer = buffer;
|
||||||
|
stream->u.mem.length = length;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_CopyTo(IStream *iface, IStream *pstm, ULARGE_INTEGER size, ULARGE_INTEGER *read_len, ULARGE_INTEGER *written)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)\n", stream);
|
||||||
|
|
||||||
|
if (read_len)
|
||||||
|
read_len->QuadPart = 0;
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
written->QuadPart = 0;
|
||||||
|
|
||||||
|
/* TODO implement */
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_Commit(IStream *iface, DWORD flags)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p, %#x)\n", stream, flags);
|
||||||
|
|
||||||
|
/* Commit is not supported by this stream */
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_Revert(IStream *iface)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)\n", stream);
|
||||||
|
|
||||||
|
/* revert not supported by this stream */
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD lock_type)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)\n", stream);
|
||||||
|
|
||||||
|
/* lock/unlock not supported by this stream */
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD lock_type)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)\n", stream);
|
||||||
|
|
||||||
|
/* lock/unlock not supported by this stream */
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI memstream_Stat(IStream *iface, STATSTG *statstg, DWORD flags)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p, %p, %#x)\n", stream, statstg, flags);
|
||||||
|
|
||||||
|
memset(statstg, 0, sizeof(*statstg));
|
||||||
|
statstg->type = STGTY_STREAM;
|
||||||
|
statstg->cbSize.QuadPart = stream->u.mem.length;
|
||||||
|
statstg->grfMode = STGM_READWRITE;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI shstream_Clone(IStream *iface, IStream **dest)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
|
||||||
|
TRACE("(%p, %p)\n", stream, dest);
|
||||||
|
|
||||||
|
*dest = NULL;
|
||||||
|
|
||||||
|
/* clone not supported by this stream */
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IStreamVtbl shstreamvtbl =
|
||||||
|
{
|
||||||
|
shstream_QueryInterface,
|
||||||
|
shstream_AddRef,
|
||||||
|
memstream_Release,
|
||||||
|
memstream_Read,
|
||||||
|
memstream_Write,
|
||||||
|
memstream_Seek,
|
||||||
|
memstream_SetSize,
|
||||||
|
shstream_CopyTo,
|
||||||
|
shstream_Commit,
|
||||||
|
shstream_Revert,
|
||||||
|
shstream_LockRegion,
|
||||||
|
shstream_UnlockRegion,
|
||||||
|
memstream_Stat,
|
||||||
|
shstream_Clone,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* SHCreateMemStream [SHCORE.@]
|
||||||
|
*
|
||||||
|
* Create an IStream object on a block of memory.
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* data [I] Memory block to create the IStream object on
|
||||||
|
* data_len [I] Length of data block
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: A pointer to the IStream object.
|
||||||
|
* Failure: NULL, if any parameters are invalid or an error occurs.
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* A copy of the memory block is made, it's freed when the stream is released.
|
||||||
|
*/
|
||||||
|
IStream * WINAPI SHCreateMemStream(const BYTE *data, UINT data_len)
|
||||||
|
{
|
||||||
|
struct shstream *stream;
|
||||||
|
|
||||||
|
TRACE("(%p, %u)\n", data, data_len);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
data_len = 0;
|
||||||
|
|
||||||
|
stream = heap_alloc(sizeof(*stream));
|
||||||
|
stream->IStream_iface.lpVtbl = &shstreamvtbl;
|
||||||
|
stream->refcount = 1;
|
||||||
|
stream->u.mem.buffer = heap_alloc(data_len);
|
||||||
|
if (!stream->u.mem.buffer)
|
||||||
|
{
|
||||||
|
heap_free(stream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(stream->u.mem.buffer, data, data_len);
|
||||||
|
stream->u.mem.length = data_len;
|
||||||
|
stream->u.mem.position = 0;
|
||||||
|
|
||||||
|
return &stream->IStream_iface;
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
@ stdcall SHAnsiToUnicode(str ptr long) shlwapi.SHAnsiToUnicode
|
@ stdcall SHAnsiToUnicode(str ptr long) shlwapi.SHAnsiToUnicode
|
||||||
@ stdcall SHCopyKeyA(long str long long) shlwapi.SHCopyKeyA
|
@ stdcall SHCopyKeyA(long str long long) shlwapi.SHCopyKeyA
|
||||||
@ stdcall SHCopyKeyW(long wstr long long) shlwapi.SHCopyKeyW
|
@ stdcall SHCopyKeyW(long wstr long long) shlwapi.SHCopyKeyW
|
||||||
@ stdcall SHCreateMemStream(ptr long) shlwapi.SHCreateMemStream
|
@ stdcall SHCreateMemStream(ptr long)
|
||||||
@ stdcall SHCreateStreamOnFileA(str long ptr) shlwapi.SHCreateStreamOnFileA
|
@ stdcall SHCreateStreamOnFileA(str long ptr) shlwapi.SHCreateStreamOnFileA
|
||||||
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr) shlwapi.SHCreateStreamOnFileEx
|
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr) shlwapi.SHCreateStreamOnFileEx
|
||||||
@ stdcall SHCreateStreamOnFileW(wstr long ptr) shlwapi.SHCreateStreamOnFileW
|
@ stdcall SHCreateStreamOnFileW(wstr long ptr) shlwapi.SHCreateStreamOnFileW
|
||||||
|
|
Loading…
Reference in New Issue