shcore: Add registry value stream functions.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ea0dbc753f
commit
d7a4556111
|
@ -1,5 +1,5 @@
|
||||||
MODULE = shcore.dll
|
MODULE = shcore.dll
|
||||||
IMPORTS = user32 gdi32 ole32
|
IMPORTS = user32 gdi32 ole32 advapi32
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
main.c
|
main.c
|
||||||
|
|
|
@ -517,6 +517,9 @@ struct shstream
|
||||||
BYTE *buffer;
|
BYTE *buffer;
|
||||||
DWORD length;
|
DWORD length;
|
||||||
DWORD position;
|
DWORD position;
|
||||||
|
|
||||||
|
HKEY hkey;
|
||||||
|
WCHAR *valuename;
|
||||||
} mem;
|
} mem;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -776,6 +779,29 @@ static const IStreamVtbl memstreamvtbl =
|
||||||
shstream_Clone,
|
shstream_Clone,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct shstream *shstream_create(const IStreamVtbl *vtbl, const BYTE *data, UINT data_len)
|
||||||
|
{
|
||||||
|
struct shstream *stream;
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
data_len = 0;
|
||||||
|
|
||||||
|
stream = heap_alloc(sizeof(*stream));
|
||||||
|
stream->IStream_iface.lpVtbl = vtbl;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* SHCreateMemStream [SHCORE.@]
|
* SHCreateMemStream [SHCORE.@]
|
||||||
*
|
*
|
||||||
|
@ -798,23 +824,8 @@ IStream * WINAPI SHCreateMemStream(const BYTE *data, UINT data_len)
|
||||||
|
|
||||||
TRACE("(%p, %u)\n", data, data_len);
|
TRACE("(%p, %u)\n", data, data_len);
|
||||||
|
|
||||||
if (!data)
|
stream = shstream_create(&memstreamvtbl, data, data_len);
|
||||||
data_len = 0;
|
return stream ? &stream->IStream_iface : NULL;
|
||||||
|
|
||||||
stream = heap_alloc(sizeof(*stream));
|
|
||||||
stream->IStream_iface.lpVtbl = &memstreamvtbl;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI filestream_Release(IStream *iface)
|
static ULONG WINAPI filestream_Release(IStream *iface)
|
||||||
|
@ -1134,6 +1145,201 @@ HRESULT WINAPI SHCreateStreamOnFileA(const char *path, DWORD mode, IStream **str
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI regstream_Release(IStream *iface)
|
||||||
|
{
|
||||||
|
struct shstream *stream = impl_from_IStream(iface);
|
||||||
|
ULONG refcount = InterlockedDecrement(&stream->refcount);
|
||||||
|
|
||||||
|
TRACE("(%p)->(%u)\n", stream, refcount);
|
||||||
|
|
||||||
|
if (!refcount)
|
||||||
|
{
|
||||||
|
if (stream->u.mem.hkey)
|
||||||
|
{
|
||||||
|
if (stream->u.mem.length)
|
||||||
|
RegSetValueExW(stream->u.mem.hkey, stream->u.mem.valuename, 0, REG_BINARY,
|
||||||
|
(const BYTE *)stream->u.mem.buffer, stream->u.mem.length);
|
||||||
|
else
|
||||||
|
RegDeleteValueW(stream->u.mem.hkey, stream->u.mem.valuename);
|
||||||
|
RegCloseKey(stream->u.mem.hkey);
|
||||||
|
}
|
||||||
|
CoTaskMemFree(stream->u.mem.valuename);
|
||||||
|
heap_free(stream->u.mem.buffer);
|
||||||
|
heap_free(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IStreamVtbl regstreamvtbl =
|
||||||
|
{
|
||||||
|
shstream_QueryInterface,
|
||||||
|
shstream_AddRef,
|
||||||
|
regstream_Release,
|
||||||
|
memstream_Read,
|
||||||
|
memstream_Write,
|
||||||
|
memstream_Seek,
|
||||||
|
memstream_SetSize,
|
||||||
|
shstream_CopyTo,
|
||||||
|
shstream_Commit,
|
||||||
|
shstream_Revert,
|
||||||
|
shstream_LockRegion,
|
||||||
|
shstream_UnlockRegion,
|
||||||
|
memstream_Stat,
|
||||||
|
shstream_Clone,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* SHOpenRegStream2W [SHCORE.@]
|
||||||
|
*/
|
||||||
|
IStream * WINAPI SHOpenRegStream2W(HKEY hKey, const WCHAR *subkey, const WCHAR *value, DWORD mode)
|
||||||
|
{
|
||||||
|
struct shstream *stream;
|
||||||
|
HKEY hStrKey = NULL;
|
||||||
|
BYTE *buff = NULL;
|
||||||
|
DWORD length = 0;
|
||||||
|
LONG ret;
|
||||||
|
|
||||||
|
TRACE("(%p, %s, %s, %#x)\n", hKey, debugstr_w(subkey), debugstr_w(value), mode);
|
||||||
|
|
||||||
|
if (mode == STGM_READ)
|
||||||
|
ret = RegOpenKeyExW(hKey, subkey, 0, KEY_READ, &hStrKey);
|
||||||
|
else /* in write mode we make sure the subkey exits */
|
||||||
|
ret = RegCreateKeyExW(hKey, subkey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hStrKey, NULL);
|
||||||
|
|
||||||
|
if (ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (mode == STGM_READ || mode == STGM_READWRITE)
|
||||||
|
{
|
||||||
|
/* read initial data */
|
||||||
|
ret = RegQueryValueExW(hStrKey, value, 0, 0, 0, &length);
|
||||||
|
if (ret == ERROR_SUCCESS && length)
|
||||||
|
{
|
||||||
|
buff = heap_alloc(length);
|
||||||
|
RegQueryValueExW(hStrKey, value, 0, 0, buff, &length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!length)
|
||||||
|
buff = heap_alloc(length);
|
||||||
|
|
||||||
|
stream = shstream_create(®streamvtbl, buff, length);
|
||||||
|
heap_free(buff);
|
||||||
|
if (stream)
|
||||||
|
{
|
||||||
|
stream->u.mem.hkey = hStrKey;
|
||||||
|
SHStrDupW(value, &stream->u.mem.valuename);
|
||||||
|
return &stream->IStream_iface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_free(buff);
|
||||||
|
if (hStrKey)
|
||||||
|
RegCloseKey(hStrKey);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* SHOpenRegStream2A [SHCORE.@]
|
||||||
|
*/
|
||||||
|
IStream * WINAPI SHOpenRegStream2A(HKEY hKey, const char *subkey, const char *value, DWORD mode)
|
||||||
|
{
|
||||||
|
WCHAR *subkeyW = NULL, *valueW = NULL;
|
||||||
|
IStream *stream;
|
||||||
|
|
||||||
|
TRACE("(%p, %s, %s, %#x)\n", hKey, debugstr_a(subkey), debugstr_a(value), mode);
|
||||||
|
|
||||||
|
if (subkey && FAILED(SHStrDupA(subkey, &subkeyW)))
|
||||||
|
return NULL;
|
||||||
|
if (value && FAILED(SHStrDupA(value, &valueW)))
|
||||||
|
{
|
||||||
|
CoTaskMemFree(subkeyW);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = SHOpenRegStream2W(hKey, subkeyW, valueW, mode);
|
||||||
|
CoTaskMemFree(subkeyW);
|
||||||
|
CoTaskMemFree(valueW);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* SHOpenRegStreamA [SHCORE.@]
|
||||||
|
*/
|
||||||
|
IStream * WINAPI SHOpenRegStreamA(HKEY hkey, const char *subkey, const char *value, DWORD mode)
|
||||||
|
{
|
||||||
|
WCHAR *subkeyW = NULL, *valueW = NULL;
|
||||||
|
IStream *stream;
|
||||||
|
|
||||||
|
TRACE("(%p, %s, %s, %#x)\n", hkey, debugstr_a(subkey), debugstr_a(value), mode);
|
||||||
|
|
||||||
|
if (subkey && FAILED(SHStrDupA(subkey, &subkeyW)))
|
||||||
|
return NULL;
|
||||||
|
if (value && FAILED(SHStrDupA(value, &valueW)))
|
||||||
|
{
|
||||||
|
CoTaskMemFree(subkeyW);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = SHOpenRegStreamW(hkey, subkeyW, valueW, mode);
|
||||||
|
CoTaskMemFree(subkeyW);
|
||||||
|
CoTaskMemFree(valueW);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI dummystream_AddRef(IStream *iface)
|
||||||
|
{
|
||||||
|
TRACE("()\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI dummystream_Release(IStream *iface)
|
||||||
|
{
|
||||||
|
TRACE("()\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI dummystream_Read(IStream *iface, void *buff, ULONG buff_size, ULONG *read_len)
|
||||||
|
{
|
||||||
|
if (read_len)
|
||||||
|
*read_len = 0;
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IStreamVtbl dummystreamvtbl =
|
||||||
|
{
|
||||||
|
shstream_QueryInterface,
|
||||||
|
dummystream_AddRef,
|
||||||
|
dummystream_Release,
|
||||||
|
dummystream_Read,
|
||||||
|
memstream_Write,
|
||||||
|
memstream_Seek,
|
||||||
|
memstream_SetSize,
|
||||||
|
shstream_CopyTo,
|
||||||
|
shstream_Commit,
|
||||||
|
shstream_Revert,
|
||||||
|
shstream_LockRegion,
|
||||||
|
shstream_UnlockRegion,
|
||||||
|
memstream_Stat,
|
||||||
|
shstream_Clone,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct shstream dummyregstream = { { &dummystreamvtbl } };
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* SHOpenRegStreamW [SHCORE.@]
|
||||||
|
*/
|
||||||
|
IStream * WINAPI SHOpenRegStreamW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, DWORD mode)
|
||||||
|
{
|
||||||
|
IStream *stream;
|
||||||
|
|
||||||
|
TRACE("(%p, %s, %s, %#x)\n", hkey, debugstr_w(subkey), debugstr_w(value), mode);
|
||||||
|
stream = SHOpenRegStream2W(hkey, subkey, value, mode);
|
||||||
|
return stream ? stream : &dummyregstream.IStream_iface;
|
||||||
|
}
|
||||||
|
|
||||||
struct threadref
|
struct threadref
|
||||||
{
|
{
|
||||||
IUnknown IUnknown_iface;
|
IUnknown IUnknown_iface;
|
||||||
|
|
|
@ -53,10 +53,10 @@
|
||||||
@ stdcall SHGetThreadRef(ptr)
|
@ stdcall SHGetThreadRef(ptr)
|
||||||
@ stdcall SHGetValueA( long str str ptr ptr ptr ) shlwapi.SHGetValueA
|
@ stdcall SHGetValueA( long str str ptr ptr ptr ) shlwapi.SHGetValueA
|
||||||
@ stdcall SHGetValueW( long wstr wstr ptr ptr ptr ) shlwapi.SHGetValueW
|
@ stdcall SHGetValueW( long wstr wstr ptr ptr ptr ) shlwapi.SHGetValueW
|
||||||
@ stdcall SHOpenRegStream2A(long str str long) shlwapi.SHOpenRegStream2A
|
@ stdcall SHOpenRegStream2A(long str str long)
|
||||||
@ stdcall SHOpenRegStream2W(long wstr wstr long) shlwapi.SHOpenRegStream2W
|
@ stdcall SHOpenRegStream2W(long wstr wstr long)
|
||||||
@ stdcall SHOpenRegStreamA(long str str long) shlwapi.SHOpenRegStreamA
|
@ stdcall SHOpenRegStreamA(long str str long)
|
||||||
@ stdcall SHOpenRegStreamW(long wstr wstr long) shlwapi.SHOpenRegStreamW
|
@ stdcall SHOpenRegStreamW(long wstr wstr long)
|
||||||
@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyA
|
@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyA
|
||||||
@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyW
|
@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyW
|
||||||
@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr) shlwapi.SHQueryValueExA
|
@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr) shlwapi.SHQueryValueExA
|
||||||
|
|
Loading…
Reference in New Issue