Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/shcore/main.c | 119 ++++++++++++++++++++++++++++++++++++++++ dlls/shcore/shcore.spec | 2 +- 2 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index 488e78eb86..93effef6ad 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -28,6 +28,7 @@ #include "initguid.h" #include "ocidl.h" #include "shellscalingapi.h" +#include "shlwapi.h"
#include "wine/debug.h" #include "wine/heap.h" @@ -1290,3 +1291,121 @@ void WINAPI SetProcessReference(IUnknown *obj)
process_ref = obj; } + +struct thread_data +{ + LPTHREAD_START_ROUTINE thread_proc; + LPTHREAD_START_ROUTINE callback; + void *data; + DWORD flags; + HANDLE hEvent; + IUnknown *thread_ref; + IUnknown *process_ref; +}; + +static DWORD WINAPI shcore_thread_wrapper(void *data) +{ + struct thread_data thread_data; + HRESULT hr = E_FAIL; + DWORD retval; + + TRACE("(%p)\n", data); + + /* We are now executing in the context of the newly created thread. + * So we copy the data passed to us (it is on the stack of the function + * that called us, which is waiting for us to signal an event before + * returning). */ + thread_data = *(struct thread_data *)data; + + if (thread_data.flags & CTF_COINIT) + { + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(hr)) + hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE); + } + + if (thread_data.callback) + thread_data.callback(thread_data.data); + + /* Signal the thread that created us; it can return now. */ + SetEvent(thread_data.hEvent); + + /* Execute the callers start code. */ + retval = thread_data.thread_proc(thread_data.data); + + /* Release thread and process references. */ + if (thread_data.thread_ref) + IUnknown_Release(thread_data.thread_ref); + + if (thread_data.process_ref) + IUnknown_Release(thread_data.process_ref); + + if (SUCCEEDED(hr)) + CoUninitialize(); + + return retval; +} + +/************************************************************************* + * SHCreateThread [SHCORE.@] + */ +BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE thread_proc, void *data, DWORD flags, LPTHREAD_START_ROUTINE callback) +{ + struct thread_data thread_data; + BOOL called = FALSE; + + TRACE("(%p, %p, %#x, %p)\n", thread_proc, data, flags, callback); + + thread_data.thread_proc = thread_proc; + thread_data.callback = callback; + thread_data.data = data; + thread_data.flags = flags; + thread_data.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + if (flags & CTF_THREAD_REF) + SHGetThreadRef(&thread_data.thread_ref); + else + thread_data.thread_ref = NULL; + + if (flags & CTF_PROCESS_REF) + GetProcessReference(&thread_data.process_ref); + else + thread_data.process_ref = NULL; + + /* Create the thread */ + if (thread_data.hEvent) + { + HANDLE hThread; + DWORD retval; + + hThread = CreateThread(NULL, 0, shcore_thread_wrapper, &thread_data, 0, &retval); + if (hThread) + { + /* Wait for the thread to signal us to continue */ + WaitForSingleObject(thread_data.hEvent, INFINITE); + CloseHandle(hThread); + called = TRUE; + } + CloseHandle(thread_data.hEvent); + } + + if (!called) + { + if (!thread_data.callback && flags & CTF_INSIST) + { + /* Couldn't call, call synchronously */ + thread_data.thread_proc(data); + called = TRUE; + } + else + { + if (thread_data.thread_ref) + IUnknown_Release(thread_data.thread_ref); + + if (thread_data.process_ref) + IUnknown_Release(thread_data.process_ref); + } + } + + return called; +} diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index c98f2db54a..a08c2da7e0 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -37,7 +37,7 @@ @ stdcall SHCreateStreamOnFileA(str long ptr) @ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr) @ stdcall SHCreateStreamOnFileW(wstr long ptr) -@ stdcall SHCreateThread(ptr ptr long ptr) shlwapi.SHCreateThread +@ stdcall SHCreateThread(ptr ptr long ptr) @ stdcall SHCreateThreadRef(ptr ptr) @ stub SHCreateThreadWithHandle @ stdcall SHDeleteEmptyKeyA(long ptr) shlwapi.SHDeleteEmptyKeyA
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/shcore/main.c | 46 +++++++++++++++++++++++++++++++++++++++++ dlls/shcore/shcore.spec | 4 ++-- 2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index 93effef6ad..bf477aefcc 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -1409,3 +1409,49 @@ BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE thread_proc, void *data, DWORD
return called; } + +/************************************************************************* + * SHStrDupW [SHCORE.@] + */ +HRESULT WINAPI SHStrDupW(const WCHAR *src, WCHAR **dest) +{ + size_t len; + + TRACE("(%s, %p)\n", debugstr_w(src), dest); + + *dest = NULL; + + if (!src) + return E_INVALIDARG; + + len = (strlenW(src) + 1) * sizeof(WCHAR); + *dest = CoTaskMemAlloc(len); + if (!*dest) + return E_OUTOFMEMORY; + + memcpy(*dest, src, len); + + return S_OK; +} + +/************************************************************************* + * SHStrDupA [SHCORE.@] + */ +HRESULT WINAPI SHStrDupA(const char *src, WCHAR **dest) +{ + DWORD len; + + *dest = NULL; + + if (!src) + return E_INVALIDARG; + + len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); + *dest = CoTaskMemAlloc(len * sizeof(WCHAR)); + if (!*dest) + return E_OUTOFMEMORY; + + MultiByteToWideChar(CP_ACP, 0, src, -1, *dest, len); + + return S_OK; +} diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index a08c2da7e0..1473bf7b0a 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -73,8 +73,8 @@ @ stdcall SHSetThreadRef(ptr) @ stdcall SHSetValueA(long str str long ptr long) shlwapi.SHSetValueA @ stdcall SHSetValueW(long wstr wstr long ptr long) shlwapi.SHSetValueW -@ stdcall SHStrDupA(str ptr) shlwapi.SHStrDupA -@ stdcall SHStrDupW(wstr ptr) shlwapi.SHStrDupW +@ stdcall SHStrDupA(str ptr) +@ stdcall SHStrDupW(wstr ptr) @ stdcall SHUnicodeToAnsi(wstr ptr ptr) shlwapi.SHUnicodeToAnsi @ stdcall SHUnicodeToUnicode(wstr ptr long) shlwapi.SHUnicodeToUnicode @ stdcall SetCurrentProcessExplicitAppUserModelID(wstr)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/shcore/main.c | 98 ++++++++++++++++++++++++++++++++++++++ dlls/shcore/shcore.spec | 8 ++-- dlls/shcore/tests/shcore.c | 52 ++++++++++++++++++++ 3 files changed, 154 insertions(+), 4 deletions(-)
diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index bf477aefcc..a0add79b3c 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -1455,3 +1455,101 @@ HRESULT WINAPI SHStrDupA(const char *src, WCHAR **dest)
return S_OK; } + +/************************************************************************* + * SHAnsiToAnsi [SHCORE.@] + */ +DWORD WINAPI SHAnsiToAnsi(const char *src, char *dest, int dest_len) +{ + DWORD ret = 0; + + TRACE("(%s, %p, %d)\n", debugstr_a(src), dest, dest_len); + + if (!src || !dest || dest_len <= 0) + return 0; + + while (dest_len > 1 && *src) + { + dest_len--; + ret++; + *dest++ = *src++; + } + + if (dest_len) + { + *dest = 0; + ret++; + } + + return ret; +} + +/************************************************************************* + * SHUnicodeToAnsi [SHCORE.@] + */ +DWORD WINAPI SHUnicodeToAnsi(const WCHAR *src, char *dest, int dest_len) +{ + char *buff; + int len; + + TRACE("(%s, %p, %d)\n", debugstr_w(src), dest, dest_len); + + len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); + buff = heap_alloc(len); + if (!buff) + return 0; + + WideCharToMultiByte(CP_ACP, 0, src, -1, buff, len, NULL, NULL); + len = SHAnsiToAnsi(buff, dest, dest_len); + heap_free(buff); + return len; +} + +/************************************************************************* + * SHUnicodeToUnicode [SHCORE.@] + */ +DWORD WINAPI SHUnicodeToUnicode(const WCHAR *src, WCHAR *dest, int dest_len) +{ + DWORD ret = 0; + + TRACE("(%s, %p, %d)\n", debugstr_w(src), dest, dest_len); + + if (!src || !dest || dest_len <= 0) + return 0; + + while (dest_len > 1 && *src) + { + dest_len--; + ret++; + *dest++ = *src++; + } + + if (dest_len) + { + *dest = 0; + ret++; + } + + return ret; +} + +/************************************************************************* + * SHAnsiToUnicode [SHCORE.@] + */ +DWORD WINAPI SHAnsiToUnicode(const char *src, WCHAR *dest, int dest_len) +{ + WCHAR *buffW; + int len; + + TRACE("(%s, %p, %d)\n", debugstr_a(src), dest, dest_len); + + len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); + buffW = heap_alloc(len * sizeof(*buffW)); + if (!buffW) + return 0; + + MultiByteToWideChar(CP_ACP, 0, src, -1, buffW, len); + len = SHUnicodeToUnicode(buffW, dest, dest_len); + heap_free(buffW); + return len; +} diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index 1473bf7b0a..918ba5595c 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -29,8 +29,8 @@ @ stub RegisterScaleChangeEvent @ stub RegisterScaleChangeNotifications @ stub RevokeScaleChangeNotifications -@ stdcall SHAnsiToAnsi(str ptr long) shlwapi.SHAnsiToAnsi -@ stdcall SHAnsiToUnicode(str ptr long) shlwapi.SHAnsiToUnicode +@ stdcall SHAnsiToAnsi(str ptr long) +@ stdcall SHAnsiToUnicode(str ptr long) @ stdcall SHCopyKeyA(long str long long) shlwapi.SHCopyKeyA @ stdcall SHCopyKeyW(long wstr long long) shlwapi.SHCopyKeyW @ stdcall SHCreateMemStream(ptr long) @@ -75,8 +75,8 @@ @ stdcall SHSetValueW(long wstr wstr long ptr long) shlwapi.SHSetValueW @ stdcall SHStrDupA(str ptr) @ stdcall SHStrDupW(wstr ptr) -@ stdcall SHUnicodeToAnsi(wstr ptr ptr) shlwapi.SHUnicodeToAnsi -@ stdcall SHUnicodeToUnicode(wstr ptr long) shlwapi.SHUnicodeToUnicode +@ stdcall SHUnicodeToAnsi(wstr ptr ptr) +@ stdcall SHUnicodeToUnicode(wstr ptr long) @ stdcall SetCurrentProcessExplicitAppUserModelID(wstr) @ stdcall SetProcessDpiAwareness(long) @ stdcall SetProcessReference(ptr) diff --git a/dlls/shcore/tests/shcore.c b/dlls/shcore/tests/shcore.c index 904d8264cd..c3851a7d53 100644 --- a/dlls/shcore/tests/shcore.c +++ b/dlls/shcore/tests/shcore.c @@ -29,12 +29,16 @@ static HRESULT (WINAPI *pGetProcessReference)(IUnknown **); static void (WINAPI *pSetProcessReference)(IUnknown *); static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown **); +static int (WINAPI *pSHUnicodeToAnsi)(const WCHAR *, char *, int); +static int (WINAPI *pSHAnsiToUnicode)(const char *, WCHAR *, int);
static void init(HMODULE hshcore) { #define X(f) p##f = (void*)GetProcAddress(hshcore, #f) X(GetProcessReference); X(SetProcessReference); + X(SHUnicodeToAnsi); + X(SHAnsiToUnicode); #undef X }
@@ -122,6 +126,52 @@ static void test_process_reference(void) ok(test_unk2.refcount == 3, "Unexpected refcount %u.\n", test_unk2.refcount); }
+static void test_SHUnicodeToAnsi(void) +{ + static const WCHAR testW[] = {'t','e','s','t',0}; + char buff[16]; + int ret; + + ret = pSHUnicodeToAnsi(NULL, NULL, 0); + ok(ret == 0, "Unexpected return value %d.\n", ret); + + buff[0] = 1; + ret = pSHUnicodeToAnsi(testW, buff, 1); + ok(ret == 1, "Unexpected return value %d.\n", ret); + ok(buff[0] == 0, "Unexpected buffer contents.\n"); + + ret = pSHUnicodeToAnsi(testW, buff, 16); + ok(ret == 5, "Unexpected return value %d.\n", ret); + ok(!strcmp(buff, "test"), "Unexpected buffer contents.\n"); + + ret = pSHUnicodeToAnsi(testW, buff, 2); + ok(ret == 2, "Unexpected return value %d.\n", ret); + ok(!strcmp(buff, "t"), "Unexpected buffer contents.\n"); +} + +static void test_SHAnsiToUnicode(void) +{ + static const WCHAR testW[] = {'t','e','s','t',0}; + WCHAR buffW[16]; + int ret; + + ret = pSHAnsiToUnicode(NULL, NULL, 0); + ok(ret == 0, "Unexpected return value %d.\n", ret); + + buffW[0] = 1; + ret = pSHAnsiToUnicode("test", buffW, 1); + ok(ret == 1, "Unexpected return value %d.\n", ret); + ok(buffW[0] == 0, "Unexpected buffer contents.\n"); + + ret = pSHAnsiToUnicode("test", buffW, 16); + ok(ret == 5, "Unexpected return value %d.\n", ret); + ok(!lstrcmpW(buffW, testW), "Unexpected buffer contents.\n"); + + ret = pSHAnsiToUnicode("test", buffW, 2); + ok(ret == 2, "Unexpected return value %d.\n", ret); + ok(buffW[0] == 't' && buffW[1] == 0, "Unexpected buffer contents.\n"); +} + START_TEST(shcore) { HMODULE hshcore = LoadLibraryA("shcore.dll"); @@ -135,4 +185,6 @@ START_TEST(shcore) init(hshcore);
test_process_reference(); + test_SHUnicodeToAnsi(); + test_SHAnsiToUnicode(); }
Nikolay Sivov nsivov@codeweavers.com wrote:
+DWORD WINAPI SHAnsiToAnsi(const char *src, char *dest, int dest_len) +{
- DWORD ret = 0;
- TRACE("(%s, %p, %d)\n", debugstr_a(src), dest, dest_len);
- if (!src || !dest || dest_len <= 0)
return 0;
- while (dest_len > 1 && *src)
- {
dest_len--;
ret++;
*dest++ = *src++;
- }
- if (dest_len)
- {
*dest = 0;
ret++;
- }
- return ret;
+}
What is the reason to duplicate lstrcpynA?
+DWORD WINAPI SHUnicodeToAnsi(const WCHAR *src, char *dest, int dest_len) +{
- char *buff;
- int len;
- TRACE("(%s, %p, %d)\n", debugstr_w(src), dest, dest_len);
- len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
- buff = heap_alloc(len);
- if (!buff)
return 0;
- WideCharToMultiByte(CP_ACP, 0, src, -1, buff, len, NULL, NULL);
- len = SHAnsiToAnsi(buff, dest, dest_len);
- heap_free(buff);
- return len;
+}
It should be possible to do without an intermediate memory allocation.
+DWORD WINAPI SHUnicodeToUnicode(const WCHAR *src, WCHAR *dest, int dest_len) +{
- DWORD ret = 0;
- TRACE("(%s, %p, %d)\n", debugstr_w(src), dest, dest_len);
- if (!src || !dest || dest_len <= 0)
return 0;
- while (dest_len > 1 && *src)
- {
dest_len--;
ret++;
*dest++ = *src++;
- }
- if (dest_len)
- {
*dest = 0;
ret++;
- }
- return ret;
+}
What is the reason to duplicate lstrcpynW?
+DWORD WINAPI SHAnsiToUnicode(const char *src, WCHAR *dest, int dest_len) +{
- WCHAR *buffW;
- int len;
- TRACE("(%s, %p, %d)\n", debugstr_a(src), dest, dest_len);
- len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
- buffW = heap_alloc(len * sizeof(*buffW));
- if (!buffW)
return 0;
- MultiByteToWideChar(CP_ACP, 0, src, -1, buffW, len);
- len = SHUnicodeToUnicode(buffW, dest, dest_len);
- heap_free(buffW);
- return len;
+}
It should be possible to do without an intermediate memory allocation.
Signed-off-by: Nikolay Sivov nsivov@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 a0add79b3c..6adbd04842 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 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
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/shcore/main.c | 12 ++++++++++++ dlls/shcore/shcore.spec | 2 +- dlls/shcore/tests/Makefile.in | 1 + dlls/shcore/tests/shcore.c | 20 ++++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index 6adbd04842..373c6ec92e 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -1759,3 +1759,15 @@ DWORD WINAPI SHAnsiToUnicode(const char *src, WCHAR *dest, int dest_len) heap_free(buffW); return len; } + +/************************************************************************* + * SHRegDuplicateHKey [SHCORE.@] + */ +HKEY WINAPI SHRegDuplicateHKey(HKEY hKey) +{ + HKEY newKey = 0; + + RegOpenKeyExW(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey); + TRACE("new key is %p\n", newKey); + return newKey; +} diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index bd2bf12df1..c7a8744a2c 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -61,7 +61,7 @@ @ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyW @ stdcall SHQueryValueExA(long str ptr ptr ptr ptr) shlwapi.SHQueryValueExA @ stdcall SHQueryValueExW(long wstr ptr ptr ptr ptr) shlwapi.SHQueryValueExW -@ stdcall SHRegDuplicateHKey(long) shlwapi.SHRegDuplicateHKey +@ stdcall SHRegDuplicateHKey(long) @ stdcall SHRegGetIntW(ptr wstr long) shlwapi.SHRegGetIntW @ stdcall SHRegGetPathA(long str str ptr long) shlwapi.SHRegGetPathA @ stdcall SHRegGetPathW(long wstr wstr ptr long) shlwapi.SHRegGetPathW diff --git a/dlls/shcore/tests/Makefile.in b/dlls/shcore/tests/Makefile.in index 0ea769a348..4f537fa387 100644 --- a/dlls/shcore/tests/Makefile.in +++ b/dlls/shcore/tests/Makefile.in @@ -1,4 +1,5 @@ TESTDLL = shcore.dll +IMPORTS = advapi32
C_SRCS = \ shcore.c diff --git a/dlls/shcore/tests/shcore.c b/dlls/shcore/tests/shcore.c index c3851a7d53..6063b17994 100644 --- a/dlls/shcore/tests/shcore.c +++ b/dlls/shcore/tests/shcore.c @@ -31,6 +31,7 @@ static void (WINAPI *pSetProcessReference)(IUnknown *); static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown **); static int (WINAPI *pSHUnicodeToAnsi)(const WCHAR *, char *, int); static int (WINAPI *pSHAnsiToUnicode)(const char *, WCHAR *, int); +static HKEY (WINAPI *pSHRegDuplicateHKey)(HKEY);
static void init(HMODULE hshcore) { @@ -39,6 +40,7 @@ static void init(HMODULE hshcore) X(SetProcessReference); X(SHUnicodeToAnsi); X(SHAnsiToUnicode); + X(SHRegDuplicateHKey); #undef X }
@@ -172,6 +174,23 @@ static void test_SHAnsiToUnicode(void) ok(buffW[0] == 't' && buffW[1] == 0, "Unexpected buffer contents.\n"); }
+static void test_SHRegDuplicateHKey(void) +{ + HKEY hkey, hkey2; + DWORD ret; + + ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\Wine\Test", &hkey); + ok(!ret, "Failed to create test key, ret %d.\n", ret); + + hkey2 = pSHRegDuplicateHKey(hkey); + ok(hkey2 != NULL && hkey2 != hkey, "Unexpected duplicate key.\n"); + + RegCloseKey(hkey2); + RegCloseKey(hkey); + + RegDeleteKeyA(HKEY_CURRENT_USER, "Software\Wine\Test"); +} + START_TEST(shcore) { HMODULE hshcore = LoadLibraryA("shcore.dll"); @@ -187,4 +206,5 @@ START_TEST(shcore) test_process_reference(); test_SHUnicodeToAnsi(); test_SHAnsiToUnicode(); + test_SHRegDuplicateHKey(); }