Commit 8a763d9e authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

windowscodecs: Cache component info objects.

parent 0c8dc2bf
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/list.h" #include "wine/list.h"
#include "wine/rbtree.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
...@@ -60,6 +61,7 @@ typedef struct { ...@@ -60,6 +61,7 @@ typedef struct {
IWICComponentInfo IWICComponentInfo_iface; IWICComponentInfo IWICComponentInfo_iface;
LONG ref; LONG ref;
CLSID clsid; CLSID clsid;
struct wine_rb_entry entry;
} ComponentInfo; } ComponentInfo;
static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value, static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value,
...@@ -1923,8 +1925,26 @@ static const struct category categories[] = { ...@@ -1923,8 +1925,26 @@ static const struct category categories[] = {
{0} {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) HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
{ {
struct wine_rb_entry *cache_entry;
ComponentInfo *info; ComponentInfo *info;
HKEY clsidkey; HKEY clsidkey;
HKEY classkey; HKEY classkey;
...@@ -1936,9 +1956,23 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) ...@@ -1936,9 +1956,23 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
BOOL found = FALSE; BOOL found = FALSE;
HRESULT hr; 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); res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
if (res != ERROR_SUCCESS) if (res != ERROR_SUCCESS)
{
LeaveCriticalSection(&component_info_cache_cs);
return HRESULT_FROM_WIN32(res); return HRESULT_FROM_WIN32(res);
}
for (category=categories; category->type; category++) for (category=categories; category->type; category++)
{ {
...@@ -1980,10 +2014,21 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) ...@@ -1980,10 +2014,21 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
RegCloseKey(clsidkey); RegCloseKey(clsidkey);
if (SUCCEEDED(hr)) 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; 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 { typedef struct {
IEnumUnknown IEnumUnknown_iface; IEnumUnknown IEnumUnknown_iface;
LONG ref; LONG ref;
......
...@@ -42,6 +42,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) ...@@ -42,6 +42,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL); DisableThreadLibraryCalls(hinstDLL);
break; break;
case DLL_PROCESS_DETACH:
ReleaseComponentInfos();
break;
} }
return WIC_DllMain(hinstDLL, fdwReason, lpvReserved); return WIC_DllMain(hinstDLL, fdwReason, lpvReserved);
......
...@@ -139,7 +139,6 @@ static void test_decoder_info(void) ...@@ -139,7 +139,6 @@ static void test_decoder_info(void)
decoder_info2 = NULL; decoder_info2 = NULL;
hr = IWICBitmapDecoder_GetDecoderInfo(decoder, &decoder_info2); hr = IWICBitmapDecoder_GetDecoderInfo(decoder, &decoder_info2);
ok(hr == S_OK, "Failed to get decoder info, hr %#x.\n", hr); 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"); ok(decoder_info == decoder_info2, "Unexpected decoder info instance.\n");
hr = IWICBitmapDecoderInfo_QueryInterface(decoder_info, &IID_IWICBitmapDecoder, (void **)&decoder2); hr = IWICBitmapDecoderInfo_QueryInterface(decoder_info, &IID_IWICBitmapDecoder, (void **)&decoder2);
...@@ -470,17 +469,38 @@ static void test_pixelformat_info(void) ...@@ -470,17 +469,38 @@ static void test_pixelformat_info(void)
IWICComponentInfo_Release(info); 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) static void test_reader_info(void)
{ {
IWICImagingFactory *factory; IWICImagingFactory *factory;
IWICComponentInfo *info; IWICComponentInfo *info, *info2;
IWICMetadataReaderInfo *reader_info; IWICMetadataReaderInfo *reader_info;
HRESULT hr; HRESULT hr;
CLSID clsid; CLSID clsid;
GUID container_formats[10]; GUID container_formats[10];
UINT count, size; UINT count, size, tid;
HANDLE thread;
WICMetadataPattern *patterns; 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, hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICImagingFactory, (void**)&factory); &IID_IWICImagingFactory, (void**)&factory);
ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
...@@ -488,6 +508,11 @@ static void test_reader_info(void) ...@@ -488,6 +508,11 @@ static void test_reader_info(void)
hr = IWICImagingFactory_CreateComponentInfo(factory, &CLSID_WICUnknownMetadataReader, &info); hr = IWICImagingFactory_CreateComponentInfo(factory, &CLSID_WICUnknownMetadataReader, &info);
ok(hr == S_OK, "CreateComponentInfo failed, hr=%x\n", hr); 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); hr = IWICComponentInfo_QueryInterface(info, &IID_IWICMetadataReaderInfo, (void**)&reader_info);
ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr); ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
......
...@@ -124,6 +124,7 @@ extern HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count, ...@@ -124,6 +124,7 @@ extern HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count,
IPropertyBag2 **property) DECLSPEC_HIDDEN; IPropertyBag2 **property) DECLSPEC_HIDDEN;
extern HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) 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; extern HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) DECLSPEC_HIDDEN;
typedef struct BmpDecoder BmpDecoder; typedef struct BmpDecoder BmpDecoder;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment