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>
This commit is contained in:
parent
0c8dc2bfba
commit
8a763d9e29
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue