[v2 PATCH 2/4] shcore: Add registry value stream functions.

Nikolay Sivov nsivov at codeweavers.com
Wed Nov 28 23:57:09 CST 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/shcore/Makefile.in |   2 +-
 dlls/shcore/main.c      | 240 +++++++++++++++++++++++++++++++++++++---
 dlls/shcore/shcore.spec |   8 +-
 3 files changed, 228 insertions(+), 22 deletions(-)

diff --git a/dlls/shcore/Makefile.in b/dlls/shcore/Makefile.in
index 050be57804..ccef84e87d 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 2f32a741f4..2c592c858c 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(&regstreamvtbl, 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 918ba5595c..bd2bf12df1 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
-- 
2.19.2




More information about the wine-devel mailing list