Module: wine Branch: master Commit: 8a763d9e2952d2d58078c37bf722b033c9d4109f URL: https://source.winehq.org/git/wine.git/?a=commit;h=8a763d9e2952d2d58078c37bf...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Mar 29 20:50:35 2018 +0200
windowscodecs: Cache component info objects.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/windowscodecs/info.c | 47 +++++++++++++++++++++++++++++++++- dlls/windowscodecs/main.c | 3 +++ dlls/windowscodecs/tests/info.c | 31 +++++++++++++++++++--- dlls/windowscodecs/wincodecs_private.h | 1 + 4 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/dlls/windowscodecs/info.c b/dlls/windowscodecs/info.c index 6d3272e..6114eef 100644 --- a/dlls/windowscodecs/info.c +++ b/dlls/windowscodecs/info.c @@ -33,6 +33,7 @@ #include "wine/debug.h" #include "wine/unicode.h" #include "wine/list.h" +#include "wine/rbtree.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
@@ -60,6 +61,7 @@ typedef struct { IWICComponentInfo IWICComponentInfo_iface; LONG ref; CLSID clsid; + struct wine_rb_entry entry; } ComponentInfo;
static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value, @@ -1923,8 +1925,26 @@ static const struct category categories[] = { {0} };
+static int ComponentInfo_Compare(const void *key, const struct wine_rb_entry *entry) +{ + ComponentInfo *info = WINE_RB_ENTRY_VALUE(entry, ComponentInfo, entry); + return memcmp(key, &info->clsid, sizeof(info->clsid)); +} + +static struct wine_rb_tree component_info_cache = { ComponentInfo_Compare }; + +static CRITICAL_SECTION component_info_cache_cs; +static CRITICAL_SECTION_DEBUG component_info_cache_cs_dbg = +{ + 0, 0, &component_info_cache_cs, + { &component_info_cache_cs_dbg.ProcessLocksList, &component_info_cache_cs_dbg.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": component_info_cache") } +}; +static CRITICAL_SECTION component_info_cache_cs = { &component_info_cache_cs_dbg, -1, 0, 0, 0, 0 }; + HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) { + struct wine_rb_entry *cache_entry; ComponentInfo *info; HKEY clsidkey; HKEY classkey; @@ -1936,9 +1956,23 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) BOOL found = FALSE; HRESULT hr;
+ EnterCriticalSection(&component_info_cache_cs); + + cache_entry = wine_rb_get(&component_info_cache, clsid); + if(cache_entry) + { + info = WINE_RB_ENTRY_VALUE(cache_entry, ComponentInfo, entry); + IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface); + LeaveCriticalSection(&component_info_cache_cs); + return S_OK; + } + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey); if (res != ERROR_SUCCESS) + { + LeaveCriticalSection(&component_info_cache_cs); return HRESULT_FROM_WIN32(res); + }
for (category=categories; category->type; category++) { @@ -1980,10 +2014,21 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) RegCloseKey(clsidkey);
if (SUCCEEDED(hr)) - *ppIInfo = &info->IWICComponentInfo_iface; + { + wine_rb_put(&component_info_cache, clsid, &info->entry); + IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface); + } + LeaveCriticalSection(&component_info_cache_cs); return hr; }
+void ReleaseComponentInfos(void) +{ + ComponentInfo *info, *next_info; + WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(info, next_info, &component_info_cache, ComponentInfo, entry) + IWICComponentInfo_Release(&info->IWICComponentInfo_iface); +} + typedef struct { IEnumUnknown IEnumUnknown_iface; LONG ref; diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c index 3bed565..6f781b8 100644 --- a/dlls/windowscodecs/main.c +++ b/dlls/windowscodecs/main.c @@ -42,6 +42,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); break; + case DLL_PROCESS_DETACH: + ReleaseComponentInfos(); + break; }
return WIC_DllMain(hinstDLL, fdwReason, lpvReserved); diff --git a/dlls/windowscodecs/tests/info.c b/dlls/windowscodecs/tests/info.c index 4a9c9c6..d00e9d8 100644 --- a/dlls/windowscodecs/tests/info.c +++ b/dlls/windowscodecs/tests/info.c @@ -139,7 +139,6 @@ static void test_decoder_info(void) decoder_info2 = NULL; hr = IWICBitmapDecoder_GetDecoderInfo(decoder, &decoder_info2); ok(hr == S_OK, "Failed to get decoder info, hr %#x.\n", hr); - todo_wine ok(decoder_info == decoder_info2, "Unexpected decoder info instance.\n");
hr = IWICBitmapDecoderInfo_QueryInterface(decoder_info, &IID_IWICBitmapDecoder, (void **)&decoder2); @@ -470,17 +469,38 @@ static void test_pixelformat_info(void) IWICComponentInfo_Release(info); }
+static DWORD WINAPI cache_across_threads_test(void *arg) +{ + IWICComponentInfo *info; + HRESULT hr; + + CoInitialize(NULL); + + hr = get_component_info(&CLSID_WICUnknownMetadataReader, &info); + ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr); + ok(info == arg, "unexpected info pointer %p\n", info); + IWICComponentInfo_Release(info); + + CoUninitialize(); + return 0; +} + static void test_reader_info(void) { IWICImagingFactory *factory; - IWICComponentInfo *info; + IWICComponentInfo *info, *info2; IWICMetadataReaderInfo *reader_info; HRESULT hr; CLSID clsid; GUID container_formats[10]; - UINT count, size; + UINT count, size, tid; + HANDLE thread; WICMetadataPattern *patterns;
+ hr = get_component_info(&CLSID_WICUnknownMetadataReader, &info2); + ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr); + IWICComponentInfo_Release(info2); + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&factory); ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); @@ -488,6 +508,11 @@ static void test_reader_info(void)
hr = IWICImagingFactory_CreateComponentInfo(factory, &CLSID_WICUnknownMetadataReader, &info); ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr); + ok(info == info2, "info != info2\n"); + + thread = CreateThread(NULL, 0, cache_across_threads_test, info, 0, &tid); + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread);
hr = IWICComponentInfo_QueryInterface(info, &IID_IWICMetadataReaderInfo, (void**)&reader_info); ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr); diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h index c2c5ce4..037bde2 100644 --- a/dlls/windowscodecs/wincodecs_private.h +++ b/dlls/windowscodecs/wincodecs_private.h @@ -124,6 +124,7 @@ extern HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count, IPropertyBag2 **property) DECLSPEC_HIDDEN;
extern HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) DECLSPEC_HIDDEN; +extern void ReleaseComponentInfos(void) DECLSPEC_HIDDEN; extern HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) DECLSPEC_HIDDEN;
typedef struct BmpDecoder BmpDecoder;