diff --git a/dlls/shcore/Makefile.in b/dlls/shcore/Makefile.in index 050be57804d..ccef84e87d0 100644 --- a/dlls/shcore/Makefile.in +++ b/dlls/shcore/Makefile.in @@ -1,5 +1,5 @@ MODULE = shcore.dll -IMPORTS = user32 gdi32 ole32 +IMPORTS = user32 gdi32 ole32 advapi32 C_SRCS = \ main.c diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index 88c36ecf2d4..1228c9d0e16 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -517,6 +517,9 @@ struct shstream BYTE *buffer; DWORD length; DWORD position; + + HKEY hkey; + WCHAR *valuename; } mem; struct { @@ -776,6 +779,29 @@ static const IStreamVtbl memstreamvtbl = 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.@] * @@ -798,23 +824,8 @@ IStream * WINAPI SHCreateMemStream(const BYTE *data, UINT data_len) TRACE("(%p, %u)\n", data, data_len); - if (!data) - data_len = 0; - - 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; + stream = shstream_create(&memstreamvtbl, data, data_len); + return stream ? &stream->IStream_iface : NULL; } static ULONG WINAPI filestream_Release(IStream *iface) @@ -1134,6 +1145,201 @@ HRESULT WINAPI SHCreateStreamOnFileA(const char *path, DWORD mode, IStream **str 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 { IUnknown IUnknown_iface; diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index 918ba5595c4..bd2bf12df1a 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -53,10 +53,10 @@ @ stdcall SHGetThreadRef(ptr) @ stdcall SHGetValueA( long str str ptr ptr ptr ) shlwapi.SHGetValueA @ stdcall SHGetValueW( long wstr wstr ptr ptr ptr ) shlwapi.SHGetValueW -@ stdcall SHOpenRegStream2A(long str str long) shlwapi.SHOpenRegStream2A -@ stdcall SHOpenRegStream2W(long wstr wstr long) shlwapi.SHOpenRegStream2W -@ stdcall SHOpenRegStreamA(long str str long) shlwapi.SHOpenRegStreamA -@ stdcall SHOpenRegStreamW(long wstr wstr long) shlwapi.SHOpenRegStreamW +@ stdcall SHOpenRegStream2A(long str str long) +@ stdcall SHOpenRegStream2W(long wstr wstr long) +@ stdcall SHOpenRegStreamA(long str str long) +@ stdcall SHOpenRegStreamW(long wstr wstr long) @ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyA @ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyW @ stdcall SHQueryValueExA(long str ptr ptr ptr ptr) shlwapi.SHQueryValueExA