Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/shcore/main.c | 138 ++++++++++++++++++++++++++++++++++++++++ dlls/shcore/shcore.spec | 8 +-- 2 files changed, 142 insertions(+), 4 deletions(-)
diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index f99479d383..7f423c1edd 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -35,6 +35,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(shcore);
+static DWORD shcore_tls; + BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { TRACE("(%p, %u, %p)\n", instance, reason, reserved); @@ -45,6 +47,12 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(instance); + shcore_tls = TlsAlloc(); + break; + case DLL_PROCESS_DETACH: + if (reserved) break; + if (shcore_tls != TLS_OUT_OF_INDEXES) + TlsFree(shcore_tls); break; }
@@ -1123,3 +1131,133 @@ HRESULT WINAPI SHCreateStreamOnFileA(const char *path, DWORD mode, IStream **str
return hr; } + +struct threadref +{ + IUnknown IUnknown_iface; + LONG *refcount; +}; + +static inline struct threadref *threadref_impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct threadref, IUnknown_iface); +} + +static HRESULT WINAPI threadref_QueryInterface(IUnknown *iface, REFIID riid, void **out) +{ + struct threadref *threadref = threadref_impl_from_IUnknown(iface); + + TRACE("(%p, %s, %p)\n", threadref, debugstr_guid(riid), out); + + if (out == NULL) + return E_POINTER; + + if (IsEqualGUID(&IID_IUnknown, riid)) + { + *out = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + *out = NULL; + WARN("Interface %s not supported.\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI threadref_AddRef(IUnknown *iface) +{ + struct threadref *threadref = threadref_impl_from_IUnknown(iface); + LONG refcount = InterlockedIncrement(threadref->refcount); + + TRACE("(%p, %d)\n", threadref, refcount); + + return refcount; +} + +static ULONG WINAPI threadref_Release(IUnknown *iface) +{ + struct threadref *threadref = threadref_impl_from_IUnknown(iface); + LONG refcount = InterlockedDecrement(threadref->refcount); + + TRACE("(%p, %d)\n", threadref, refcount); + + if (!refcount) + heap_free(threadref); + + return refcount; +} + +static const IUnknownVtbl threadrefvtbl = +{ + threadref_QueryInterface, + threadref_AddRef, + threadref_Release, +}; + +/************************************************************************* + * SHCreateThreadRef [SHCORE.@] + */ +HRESULT WINAPI SHCreateThreadRef(LONG *refcount, IUnknown **out) +{ + struct threadref *threadref; + + TRACE("(%p, %p)\n", refcount, out); + + if (!refcount || !out) + return E_INVALIDARG; + + *out = NULL; + + threadref = heap_alloc(sizeof(*threadref)); + if (!threadref) + return E_OUTOFMEMORY; + threadref->IUnknown_iface.lpVtbl = &threadrefvtbl; + threadref->refcount = refcount; + + *refcount = 1; + *out = &threadref->IUnknown_iface; + + TRACE("Created %p.\n", threadref); + return S_OK; +} + +/************************************************************************* + * SHGetThreadRef [SHCORE.@] + */ +HRESULT WINAPI SHGetThreadRef(IUnknown **out) +{ + TRACE("(%p)\n", out); + + if (shcore_tls == TLS_OUT_OF_INDEXES) + return E_NOINTERFACE; + + *out = TlsGetValue(shcore_tls); + if (!*out) + return E_NOINTERFACE; + + IUnknown_AddRef(*out); + return S_OK; +} + +/************************************************************************* + * SHSetThreadRef [SHCORE.@] + */ +HRESULT WINAPI SHSetThreadRef(IUnknown *obj) +{ + TRACE("(%p)\n", obj); + + if (shcore_tls == TLS_OUT_OF_INDEXES) + return E_NOINTERFACE; + + TlsSetValue(shcore_tls, obj); + return S_OK; +} + +/************************************************************************* + * SHReleaseThreadRef [SHCORE.@] + */ +HRESULT WINAPI SHReleaseThreadRef(void) +{ + FIXME("() - stub!\n"); + return S_OK; +} diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index c3bb8d27e4..568cb20597 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -38,7 +38,7 @@ @ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr) @ stdcall SHCreateStreamOnFileW(wstr long ptr) @ stdcall SHCreateThread(ptr ptr long ptr) shlwapi.SHCreateThread -@ stdcall SHCreateThreadRef(ptr ptr) shlwapi.SHCreateThreadRef +@ stdcall SHCreateThreadRef(ptr ptr) @ stub SHCreateThreadWithHandle @ stdcall SHDeleteEmptyKeyA(long ptr) shlwapi.SHDeleteEmptyKeyA @ stdcall SHDeleteEmptyKeyW(long ptr) shlwapi.SHDeleteEmptyKeyW @@ -50,7 +50,7 @@ @ stdcall SHEnumKeyExW(long long wstr ptr) shlwapi.SHEnumKeyExW @ stdcall SHEnumValueA(long long str ptr ptr ptr ptr) shlwapi.SHEnumValueA @ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr) shlwapi.SHEnumValueW -@ stdcall SHGetThreadRef(ptr) shlwapi.SHGetThreadRef +@ 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 @@ -69,8 +69,8 @@ @ stdcall SHRegGetValueW( long wstr wstr long ptr ptr ptr ) shlwapi.SHRegGetValueW @ stdcall SHRegSetPathA(long str str str long) shlwapi.SHRegSetPathA @ stdcall SHRegSetPathW(long wstr wstr wstr long) shlwapi.SHRegSetPathW -@ stdcall SHReleaseThreadRef() shlwapi.SHReleaseThreadRef -@ stdcall SHSetThreadRef(ptr) shlwapi.SHSetThreadRef +@ stdcall SHReleaseThreadRef() +@ 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