[PATCH 1/3] dwrite: Improve font objects refcounting

Nikolay Sivov nsivov at codeweavers.com
Tue Apr 11 06:21:32 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

This fixes virtual memory exhaustion when running tests,
especially important on macos that's shipped with more fonts by default
than average clean Linux installation.

 dlls/dwrite/dwrite_private.h |  15 +-
 dlls/dwrite/font.c           | 186 +++++++++-------
 dlls/dwrite/gdiinterop.c     |  40 +++-
 dlls/dwrite/main.c           |  79 ++++---
 dlls/dwrite/tests/font.c     | 512 ++++++++++++++++++++++++++++++++++++-------
 5 files changed, 617 insertions(+), 215 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 4eed73c1f0..886beb7c57 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -118,12 +118,6 @@ static inline BOOL is_simulation_valid(DWRITE_FONT_SIMULATIONS simulations)
         DWRITE_FONT_SIMULATIONS_OBLIQUE)) == 0;
 }
 
-struct gdiinterop
-{
-    IDWriteGdiInterop1 IDWriteGdiInterop1_iface;
-    IDWriteFactory4 *factory;
-};
-
 struct textlayout_desc
 {
     IDWriteFactory4 *factory;
@@ -169,7 +163,6 @@ extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT
 extern HRESULT create_textlayout(const struct textlayout_desc*,IDWriteTextLayout**) DECLSPEC_HIDDEN;
 extern HRESULT create_trimmingsign(IDWriteFactory4*,IDWriteTextFormat*,IDWriteInlineObject**) DECLSPEC_HIDDEN;
 extern HRESULT create_typography(IDWriteTypography**) DECLSPEC_HIDDEN;
-extern void    gdiinterop_init(struct gdiinterop*,IDWriteFactory4*) DECLSPEC_HIDDEN;
 extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
 extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
 extern HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **strings) DECLSPEC_HIDDEN;
@@ -179,7 +172,7 @@ extern HRESULT get_eudc_fontcollection(IDWriteFactory4*,IDWriteFontCollection**)
 extern HRESULT get_textanalyzer(IDWriteTextAnalyzer**) DECLSPEC_HIDDEN;
 extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN;
 extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DECLSPEC_HIDDEN;
-extern HRESULT create_fontface(const struct fontface_desc*,IDWriteFontFace4**) DECLSPEC_HIDDEN;
+extern HRESULT create_fontface(const struct fontface_desc*,struct list*,IDWriteFontFace4**) DECLSPEC_HIDDEN;
 extern HRESULT create_font_collection(IDWriteFactory4*,IDWriteFontFileEnumerator*,BOOL,IDWriteFontCollection1**) DECLSPEC_HIDDEN;
 extern HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc*,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN;
 extern BOOL    is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN;
@@ -198,9 +191,13 @@ extern HRESULT create_fontfacereference(IDWriteFactory4*,IDWriteFontFile*,UINT32
     IDWriteFontFaceReference**) DECLSPEC_HIDDEN;
 extern HRESULT factory_get_cached_fontface(IDWriteFactory4*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace**,
     struct list**) DECLSPEC_HIDDEN;
-extern void    factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN;
+extern void factory_detach_fontcollection(IDWriteFactory4*,IDWriteFontCollection1*) DECLSPEC_HIDDEN;
+extern void factory_detach_gdiinterop(IDWriteFactory4*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN;
+extern struct fontfacecached *factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN;
+extern void factory_release_cached_fontface(struct fontfacecached*) DECLSPEC_HIDDEN;
 extern void    get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN;
 extern void    get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN;
+extern HRESULT create_gdiinterop(IDWriteFactory4*,IDWriteGdiInterop1**) DECLSPEC_HIDDEN;
 
 /* Opentype font table functions */
 struct dwrite_font_props {
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 096c7f3fa7..aeebb0d749 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -83,7 +83,6 @@ struct dwrite_font_data {
     IDWriteLocalizedStrings *names;
 
     /* data needed to create fontface instance */
-    IDWriteFactory4 *factory;
     DWRITE_FONT_FACE_TYPE face_type;
     IDWriteFontFile *file;
     UINT32 face_index;
@@ -99,15 +98,6 @@ struct dwrite_font_data {
     BOOL oblique_sim_tested : 1;
 };
 
-struct dwrite_fontlist {
-    IDWriteFontList1 IDWriteFontList1_iface;
-    LONG ref;
-
-    IDWriteFontFamily1 *family;
-    struct dwrite_font_data **fonts;
-    UINT32 font_count;
-};
-
 struct dwrite_fontfamily_data {
     LONG ref;
 
@@ -125,6 +115,7 @@ struct dwrite_fontcollection {
     IDWriteFontCollection1 IDWriteFontCollection1_iface;
     LONG ref;
 
+    IDWriteFactory4 *factory;
     struct dwrite_fontfamily_data **family_data;
     UINT32 family_count;
     UINT32 family_alloc;
@@ -135,18 +126,25 @@ struct dwrite_fontfamily {
     LONG ref;
 
     struct dwrite_fontfamily_data *data;
+    struct dwrite_fontcollection *collection;
+};
 
-    IDWriteFontCollection1 *collection;
+struct dwrite_fontlist {
+    IDWriteFontList1 IDWriteFontList1_iface;
+    LONG ref;
+
+    struct dwrite_font_data **fonts;
+    UINT32 font_count;
+    struct dwrite_fontfamily *family;
 };
 
 struct dwrite_font {
     IDWriteFont3 IDWriteFont3_iface;
     LONG ref;
 
-    IDWriteFontFamily1 *family;
-
     DWRITE_FONT_STYLE style;
     struct dwrite_font_data *data;
+    struct dwrite_fontfamily *family;
 };
 
 struct dwrite_fonttable {
@@ -223,6 +221,9 @@ struct dwrite_fontface {
     UINT32 file_count;
     UINT32 index;
 
+    IDWriteFactory4 *factory;
+    struct fontfacecached *cached;
+
     USHORT simulations;
     DWRITE_FONT_FACE_TYPE type;
     DWRITE_FONT_METRICS1 metrics;
@@ -418,7 +419,6 @@ static void release_font_data(struct dwrite_font_data *data)
         IDWriteLocalizedStrings_Release(data->names);
 
     IDWriteFontFile_Release(data->file);
-    IDWriteFactory4_Release(data->factory);
     heap_free(data->facename);
     heap_free(data);
 }
@@ -500,6 +500,8 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace4 *iface)
             heap_free(This->glyphs[i]);
 
         freetype_notify_cacheremove(iface);
+        factory_release_cached_fontface(This->cached);
+        IDWriteFactory4_Release(This->factory);
         heap_free(This);
     }
 
@@ -1355,25 +1357,21 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace4
 
     *fontface = NULL;
 
-    hr = factory_get_cached_fontface(data->factory, &data->file, data->face_index,
-        font->data->simulations, (IDWriteFontFace**)fontface, &cached_list);
-    if (hr != S_FALSE)
+    hr = factory_get_cached_fontface(font->family->collection->factory, &data->file, data->face_index,
+        font->data->simulations, (IDWriteFontFace **)fontface, &cached_list);
+    if (hr == S_OK) {
+        IDWriteFontFace4_AddRef(*fontface);
         return hr;
+    }
 
-    desc.factory = data->factory;
+    desc.factory = font->family->collection->factory;
     desc.face_type = data->face_type;
     desc.files = &data->file;
     desc.files_number = 1;
     desc.index = data->face_index;
     desc.simulations = data->simulations;
     desc.font_data = data;
-    hr = create_fontface(&desc, fontface);
-    if (FAILED(hr))
-        return hr;
-
-    factory_cache_fontface(cached_list, *fontface);
-
-    return S_OK;
+    return create_fontface(&desc, cached_list, fontface);
 }
 
 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont3 *iface, REFIID riid, void **obj)
@@ -1413,7 +1411,7 @@ static ULONG WINAPI dwritefont_Release(IDWriteFont3 *iface)
     TRACE("(%p)->(%d)\n", This, ref);
 
     if (!ref) {
-        IDWriteFontFamily1_Release(This->family);
+        IDWriteFontFamily1_Release(&This->family->IDWriteFontFamily1_iface);
         release_font_data(This->data);
         heap_free(This);
     }
@@ -1457,6 +1455,7 @@ static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface)
     struct dwrite_font *This = impl_from_IDWriteFont3(iface);
     IDWriteFontFace4 *fontface;
     HRESULT hr;
+    BOOL ret;
 
     TRACE("(%p)\n", This);
 
@@ -1464,7 +1463,9 @@ static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface)
     if (FAILED(hr))
         return FALSE;
 
-    return IDWriteFontFace4_IsSymbolFont(fontface);
+    ret = IDWriteFontFace4_IsSymbolFont(fontface);
+    IDWriteFontFace4_Release(fontface);
+    return ret;
 }
 
 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont3 *iface, IDWriteLocalizedStrings **names)
@@ -1507,10 +1508,11 @@ static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont3 *iface,
 
         if (table_exists) {
             hr = opentype_get_font_info_strings(table_data, stringid, &data->info_strings[stringid]);
+            IDWriteFontFace4_ReleaseFontTable(fontface, context);
             if (FAILED(hr) || !data->info_strings[stringid])
                 return hr;
-            IDWriteFontFace4_ReleaseFontTable(fontface, context);
         }
+        IDWriteFontFace4_Release(fontface);
     }
 
     hr = clone_localizedstring(data->info_strings[stringid], strings);
@@ -1555,6 +1557,7 @@ static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont3 *iface, UINT32 value,
     hr = IDWriteFontFace4_GetGlyphIndices(fontface, &value, 1, &index);
     if (FAILED(hr))
         return hr;
+    IDWriteFontFace4_Release(fontface);
 
     *exists = index != 0;
     return S_OK;
@@ -1593,7 +1596,9 @@ static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 m
     if (FAILED(hr))
         return hr;
 
-    return IDWriteFontFace4_GetUnicodeRanges(fontface, max_count, ranges, count);
+    hr = IDWriteFontFace4_GetUnicodeRanges(fontface, max_count, ranges, count);
+    IDWriteFontFace4_Release(fontface);
+    return hr;
 }
 
 static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface)
@@ -1601,6 +1606,7 @@ static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface)
     struct dwrite_font *This = impl_from_IDWriteFont3(iface);
     IDWriteFontFace4 *fontface;
     HRESULT hr;
+    BOOL ret;
 
     TRACE("(%p)\n", This);
 
@@ -1608,7 +1614,9 @@ static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface)
     if (FAILED(hr))
         return FALSE;
 
-    return IDWriteFontFace4_IsMonospacedFont(fontface);
+    ret = IDWriteFontFace4_IsMonospacedFont(fontface);
+    IDWriteFontFace4_Release(fontface);
+    return ret;
 }
 
 static BOOL WINAPI dwritefont2_IsColorFont(IDWriteFont3 *iface)
@@ -1616,6 +1624,7 @@ static BOOL WINAPI dwritefont2_IsColorFont(IDWriteFont3 *iface)
     struct dwrite_font *This = impl_from_IDWriteFont3(iface);
     IDWriteFontFace4 *fontface;
     HRESULT hr;
+    BOOL ret;
 
     TRACE("(%p)\n", This);
 
@@ -1623,21 +1632,18 @@ static BOOL WINAPI dwritefont2_IsColorFont(IDWriteFont3 *iface)
     if (FAILED(hr))
         return FALSE;
 
-    return IDWriteFontFace4_IsColorFont(fontface);
+    ret = IDWriteFontFace4_IsColorFont(fontface);
+    IDWriteFontFace4_Release(fontface);
+    return ret;
 }
 
 static HRESULT WINAPI dwritefont3_CreateFontFace(IDWriteFont3 *iface, IDWriteFontFace3 **fontface)
 {
     struct dwrite_font *This = impl_from_IDWriteFont3(iface);
-    HRESULT hr;
 
     TRACE("(%p)->(%p)\n", This, fontface);
 
-    hr = get_fontface_from_font(This, (IDWriteFontFace4**)fontface);
-    if (hr == S_OK)
-        IDWriteFontFace3_AddRef(*fontface);
-
-    return hr;
+    return get_fontface_from_font(This, (IDWriteFontFace4 **)fontface);
 }
 
 static BOOL WINAPI dwritefont3_Equals(IDWriteFont3 *iface, IDWriteFont *font)
@@ -1653,8 +1659,8 @@ static HRESULT WINAPI dwritefont3_GetFontFaceReference(IDWriteFont3 *iface, IDWr
 
     TRACE("(%p)->(%p)\n", This, reference);
 
-    return IDWriteFactory4_CreateFontFaceReference_(This->data->factory, This->data->file, This->data->face_index,
-        This->data->simulations, reference);
+    return IDWriteFactory4_CreateFontFaceReference_(This->family->collection->factory, This->data->file,
+            This->data->face_index, This->data->simulations, reference);
 }
 
 static BOOL WINAPI dwritefont3_HasCharacter(IDWriteFont3 *iface, UINT32 ch)
@@ -1731,18 +1737,20 @@ void get_logfont_from_fontface(IDWriteFontFace *iface, LOGFONTW *lf)
     *lf = fontface->lf;
 }
 
-static HRESULT create_font(struct dwrite_font_data *data, IDWriteFontFamily1 *family, IDWriteFont3 **font)
+static HRESULT create_font(struct dwrite_font_data *data, struct dwrite_fontfamily *family, IDWriteFont3 **font)
 {
     struct dwrite_font *This;
+
     *font = NULL;
 
-    This = heap_alloc(sizeof(struct dwrite_font));
-    if (!This) return E_OUTOFMEMORY;
+    This = heap_alloc(sizeof(*This));
+    if (!This)
+        return E_OUTOFMEMORY;
 
     This->IDWriteFont3_iface.lpVtbl = &dwritefontvtbl;
     This->ref = 1;
     This->family = family;
-    IDWriteFontFamily1_AddRef(family);
+    IDWriteFontFamily1_AddRef(&family->IDWriteFontFamily1_iface);
     This->style = data->style;
     This->data = data;
     InterlockedIncrement(&This->data->ref);
@@ -1792,7 +1800,7 @@ static ULONG WINAPI dwritefontlist_Release(IDWriteFontList1 *iface)
 
         for (i = 0; i < This->font_count; i++)
             release_font_data(This->fonts[i]);
-        IDWriteFontFamily1_Release(This->family);
+        IDWriteFontFamily1_Release(&This->family->IDWriteFontFamily1_iface);
         heap_free(This->fonts);
         heap_free(This);
     }
@@ -1803,7 +1811,7 @@ static ULONG WINAPI dwritefontlist_Release(IDWriteFontList1 *iface)
 static HRESULT WINAPI dwritefontlist_GetFontCollection(IDWriteFontList1 *iface, IDWriteFontCollection **collection)
 {
     struct dwrite_fontlist *This = impl_from_IDWriteFontList1(iface);
-    return IDWriteFontFamily1_GetFontCollection(This->family, collection);
+    return IDWriteFontFamily1_GetFontCollection(&This->family->IDWriteFontFamily1_iface, collection);
 }
 
 static UINT32 WINAPI dwritefontlist_GetFontCount(IDWriteFontList1 *iface)
@@ -1827,7 +1835,7 @@ static HRESULT WINAPI dwritefontlist_GetFont(IDWriteFontList1 *iface, UINT32 ind
     if (index >= This->font_count)
         return E_INVALIDARG;
 
-    return create_font(This->fonts[index], This->family, (IDWriteFont3**)font);
+    return create_font(This->fonts[index], This->family, (IDWriteFont3 **)font);
 }
 
 static DWRITE_LOCALITY WINAPI dwritefontlist1_GetFontLocality(IDWriteFontList1 *iface, UINT32 index)
@@ -1926,7 +1934,7 @@ static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily1 *iface)
 
     if (!ref)
     {
-        IDWriteFontCollection1_Release(This->collection);
+        IDWriteFontCollection1_Release(&This->collection->IDWriteFontCollection1_iface);
         release_fontfamily_data(This->data);
         heap_free(This);
     }
@@ -1966,7 +1974,7 @@ static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily1 *iface, UINT32
     if (index >= This->data->font_count)
         return E_INVALIDARG;
 
-    return create_font(This->data->fonts[index], iface, (IDWriteFont3**)font);
+    return create_font(This->data->fonts[index], This, (IDWriteFont3 **)font);
 }
 
 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily1 *iface, IDWriteLocalizedStrings **names)
@@ -2039,7 +2047,7 @@ static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1 *
             match = This->data->fonts[i];
     }
 
-    return create_font(match, iface, (IDWriteFont3**)font);
+    return create_font(match, This, (IDWriteFont3 **)font);
 }
 
 typedef BOOL (*matching_filter_func)(const struct dwrite_font_data*);
@@ -2102,8 +2110,8 @@ static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1 *ifac
 
     fonts->IDWriteFontList1_iface.lpVtbl = &dwritefontlistvtbl;
     fonts->ref = 1;
-    fonts->family = iface;
-    IDWriteFontFamily1_AddRef(fonts->family);
+    fonts->family = This;
+    IDWriteFontFamily1_AddRef(&fonts->family->IDWriteFontFamily1_iface);
     fonts->font_count = 0;
 
     /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
@@ -2155,7 +2163,7 @@ static HRESULT WINAPI dwritefontfamily1_GetFont(IDWriteFontFamily1 *iface, UINT3
     if (index >= This->data->font_count)
         return E_FAIL;
 
-    return create_font(This->data->fonts[index], iface, font);
+    return create_font(This->data->fonts[index], This, font);
 }
 
 static HRESULT WINAPI dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1 *iface, UINT32 index,
@@ -2194,7 +2202,8 @@ static const IDWriteFontFamily1Vtbl fontfamilyvtbl = {
     dwritefontfamily1_GetFontFaceReference
 };
 
-static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, IDWriteFontCollection1 *collection, IDWriteFontFamily1 **family)
+static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, struct dwrite_fontcollection *collection,
+        IDWriteFontFamily1 **family)
 {
     struct dwrite_fontfamily *This;
 
@@ -2206,7 +2215,7 @@ static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, IDWriteFon
     This->IDWriteFontFamily1_iface.lpVtbl = &fontfamilyvtbl;
     This->ref = 1;
     This->collection = collection;
-    IDWriteFontCollection1_AddRef(collection);
+    IDWriteFontCollection1_AddRef(&collection->IDWriteFontCollection1_iface);
     This->data = data;
     InterlockedIncrement(&This->data->ref);
 
@@ -2272,12 +2281,15 @@ static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection1 *iface)
 
 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection1 *iface)
 {
-    unsigned int i;
     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection1(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
+
     TRACE("(%p)->(%d)\n", This, ref);
 
     if (!ref) {
+        int i;
+
+        factory_detach_fontcollection(This->factory, iface);
         for (i = 0; i < This->family_count; i++)
             release_fontfamily_data(This->family_data[i]);
         heap_free(This->family_data);
@@ -2305,7 +2317,7 @@ static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection1
         return E_FAIL;
     }
 
-    return create_fontfamily(This->family_data[index], iface, (IDWriteFontFamily1**)family);
+    return create_fontfamily(This->family_data[index], This, (IDWriteFontFamily1 **)family);
 }
 
 static UINT32 collection_find_family(struct dwrite_fontcollection *collection, const WCHAR *name)
@@ -2399,11 +2411,11 @@ static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollec
     if (!found_font)
         return DWRITE_E_NOFONT;
 
-    hr = create_fontfamily(found_family, iface, &family);
+    hr = create_fontfamily(found_family, This, &family);
     if (FAILED(hr))
         return hr;
 
-    hr = create_font(found_font, family, (IDWriteFont3**)font);
+    hr = create_font(found_font, impl_from_IDWriteFontFamily1(family), (IDWriteFont3 **)font);
     IDWriteFontFamily1_Release(family);
     return hr;
 }
@@ -2428,7 +2440,7 @@ static HRESULT WINAPI dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
         return E_FAIL;
     }
 
-    return create_fontfamily(This->family_data[index], iface, family);
+    return create_fontfamily(This->family_data[index], This, family);
 }
 
 static const IDWriteFontCollection1Vtbl fontcollectionvtbl = {
@@ -2495,9 +2507,7 @@ static HRESULT fontcollection_add_family(struct dwrite_fontcollection *collectio
         collection->family_data = new_list;
     }
 
-    collection->family_data[collection->family_count] = family;
-    collection->family_count++;
-
+    collection->family_data[collection->family_count++] = family;
     return S_OK;
 }
 
@@ -3272,7 +3282,6 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
     }
 
     data->ref = 1;
-    data->factory = desc->factory;
     data->file = desc->files[0];
     data->face_index = desc->index;
     data->face_type = desc->face_type;
@@ -3280,7 +3289,6 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
     data->bold_sim_tested = 0;
     data->oblique_sim_tested = 0;
     IDWriteFontFile_AddRef(data->file);
-    IDWriteFactory4_AddRef(data->factory);
 
     stream_desc.stream = stream;
     stream_desc.face_type = desc->face_type;
@@ -3317,12 +3325,13 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
     return S_OK;
 }
 
-static HRESULT init_font_data_from_font(const struct dwrite_font_data *src, DWRITE_FONT_SIMULATIONS sim, const WCHAR *facenameW,
-    struct dwrite_font_data **ret)
+static HRESULT init_font_data_from_font(const struct dwrite_font_data *src, DWRITE_FONT_SIMULATIONS sim,
+        const WCHAR *facenameW, struct dwrite_font_data **ret)
 {
     struct dwrite_font_data *data;
 
     *ret = NULL;
+
     data = heap_alloc_zero(sizeof(*data));
     if (!data)
         return E_OUTOFMEMORY;
@@ -3336,7 +3345,6 @@ static HRESULT init_font_data_from_font(const struct dwrite_font_data *src, DWRI
         data->style = DWRITE_FONT_STYLE_OBLIQUE;
     memset(data->info_strings, 0, sizeof(data->info_strings));
     data->names = NULL;
-    IDWriteFactory4_AddRef(data->factory);
     IDWriteFontFile_AddRef(data->file);
 
     create_localizedstrings(&data->names);
@@ -3738,6 +3746,9 @@ HRESULT create_font_collection(IDWriteFactory4 *factory, IDWriteFontFileEnumerat
     if (is_system)
         fontcollection_add_replacements(collection);
 
+    collection->factory = factory;
+    IDWriteFactory4_AddRef(factory);
+
     return hr;
 }
 
@@ -3749,6 +3760,9 @@ struct system_fontfile_enumerator
     IDWriteFactory4 *factory;
     HKEY hkey;
     int index;
+
+    WCHAR *value;
+    DWORD max_val_count;
 };
 
 static inline struct system_fontfile_enumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface)
@@ -3783,6 +3797,7 @@ static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator *
     if (!ref) {
         IDWriteFactory4_Release(enumerator->factory);
         RegCloseKey(enumerator->hkey);
+        heap_free(enumerator->value);
         heap_free(enumerator);
     }
 
@@ -3852,29 +3867,30 @@ static HRESULT WINAPI systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFil
 static HRESULT WINAPI systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
 {
     struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
-    DWORD ret, max_val_count;
-    WCHAR *value;
 
     *current = FALSE;
     enumerator->index++;
 
-    ret = RegQueryInfoKeyW(enumerator->hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val_count, NULL, NULL, NULL);
-    if (ret != ERROR_SUCCESS)
-        return E_FAIL;
+    if (!enumerator->value) {
+        if (RegQueryInfoKeyW(enumerator->hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                &enumerator->max_val_count, NULL, NULL, NULL))
+            return E_FAIL;
 
-    max_val_count++;
-    if (!(value = heap_alloc( max_val_count * sizeof(value[0]) )))
-        return E_OUTOFMEMORY;
+        enumerator->max_val_count++;
+        if (!(enumerator->value = heap_alloc(enumerator->max_val_count * sizeof(*enumerator->value))))
+            return E_OUTOFMEMORY;
+    }
 
     /* iterate until we find next string value */
-    while (1) {
+    for (;;) {
         DWORD type = 0, count, val_count;
 
-        val_count = max_val_count;
-        value[0] = 0;
-        if (RegEnumValueW(enumerator->hkey, enumerator->index, value, &val_count, NULL, &type, NULL, &count))
+        val_count = enumerator->max_val_count;
+        *enumerator->value = 0;
+        if (RegEnumValueW(enumerator->hkey, enumerator->index, enumerator->value, &val_count,
+                NULL, &type, NULL, &count))
             break;
-        if (type == REG_SZ && *value && *value != '@') {
+        if (type == REG_SZ && *enumerator->value && *enumerator->value != '@') {
             *current = TRUE;
             break;
         }
@@ -3882,7 +3898,6 @@ static HRESULT WINAPI systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerato
     }
 
     TRACE("index = %d, current = %d\n", enumerator->index, *current);
-    heap_free(value);
     return S_OK;
 }
 
@@ -3914,6 +3929,8 @@ static HRESULT create_system_fontfile_enumerator(IDWriteFactory4 *factory, IDWri
     enumerator->ref = 1;
     enumerator->factory = factory;
     enumerator->index = -1;
+    enumerator->value = NULL;
+    enumerator->max_val_count = 0;
     IDWriteFactory4_AddRef(factory);
 
     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, fontslistW, 0, GENERIC_READ, &enumerator->hkey)) {
@@ -4238,7 +4255,7 @@ static HRESULT get_stream_from_file(IDWriteFontFile *file, IDWriteFontFileStream
     return hr;
 }
 
-HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace4 **ret)
+HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_list, IDWriteFontFace4 **ret)
 {
     struct file_stream_desc stream_desc;
     struct dwrite_fontface *fontface;
@@ -4346,6 +4363,9 @@ HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace4 **ret
         release_font_data(data);
     }
 
+    fontface->cached = factory_cache_fontface(cached_list, &fontface->IDWriteFontFace4_iface);
+    IDWriteFactory4_AddRef(fontface->factory = desc->factory);
+
     *ret = &fontface->IDWriteFontFace4_iface;
     return S_OK;
 }
@@ -5627,7 +5647,7 @@ static HRESULT WINAPI fontfacereference_CreateFontFaceWithSimulations(IDWriteFon
 
     hr = IDWriteFactory4_CreateFontFace(This->factory, face_type, 1, &This->file, This->index, simulations, &fontface);
     if (SUCCEEDED(hr)) {
-        hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace4, (void**)ret);
+        hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace3, (void **)ret);
         IDWriteFontFace_Release(fontface);
     }
 
diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c
index 67fc4a0f68..cf3b3fa10c 100644
--- a/dlls/dwrite/gdiinterop.c
+++ b/dlls/dwrite/gdiinterop.c
@@ -52,6 +52,12 @@ struct rendertarget {
     struct dib_data dib;
 };
 
+struct gdiinterop {
+    IDWriteGdiInterop1 IDWriteGdiInterop1_iface;
+    LONG ref;
+    IDWriteFactory4 *factory;
+};
+
 static inline int get_dib_stride(int width, int bpp)
 {
     return ((width * bpp + 31) >> 3) & ~3;
@@ -598,15 +604,24 @@ static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop1 *iface, REFII
 static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop1 *iface)
 {
     struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-    TRACE("(%p)\n", This);
-    return IDWriteFactory4_AddRef(This->factory);
+    LONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p)->(%d)\n", This, ref);
+    return ref;
 }
 
 static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop1 *iface)
 {
     struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
-    TRACE("(%p)\n", This);
-    return IDWriteFactory4_Release(This->factory);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p)->(%d)\n", This, ref);
+
+    if (!ref) {
+        factory_detach_gdiinterop(This->factory, iface);
+        heap_free(This);
+    }
+
+    return ref;
 }
 
 static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface,
@@ -890,10 +905,19 @@ static const struct IDWriteGdiInterop1Vtbl gdiinteropvtbl = {
     gdiinterop1_GetMatchingFontsByLOGFONT
 };
 
-void gdiinterop_init(struct gdiinterop *interop, IDWriteFactory4 *factory)
+HRESULT create_gdiinterop(IDWriteFactory4 *factory, IDWriteGdiInterop1 **ret)
 {
+    struct gdiinterop *interop;
+
+    *ret = NULL;
+
+    if (!(interop = heap_alloc(sizeof(*interop))))
+        return E_OUTOFMEMORY;
+
     interop->IDWriteGdiInterop1_iface.lpVtbl = &gdiinteropvtbl;
-    /* Interop is a part of a factory, sharing its refcount.
-       GetGdiInterop() will AddRef() on every call. */
-    interop->factory = factory;
+    interop->ref = 1;
+    IDWriteFactory4_AddRef(interop->factory = factory);
+
+    *ret = &interop->IDWriteGdiInterop1_iface;
+    return S_OK;
 }
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 067bc8a3ce..c17bb5a3a7 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -538,7 +538,7 @@ struct dwritefactory {
 
     IDWriteFontCollection1 *system_collection;
     IDWriteFontCollection *eudc_collection;
-    struct gdiinterop interop;
+    IDWriteGdiInterop1 *gdiinterop;
     IDWriteFontFallback *fallback;
 
     IDWriteLocalFontFileLoader* localfontfileloader;
@@ -556,9 +556,9 @@ static inline struct dwritefactory *impl_from_IDWriteFactory4(IDWriteFactory4 *i
 static void release_fontface_cache(struct list *fontfaces)
 {
     struct fontfacecached *fontface, *fontface2;
+
     LIST_FOR_EACH_ENTRY_SAFE(fontface, fontface2, fontfaces, struct fontfacecached, entry) {
         list_remove(&fontface->entry);
-        IDWriteFontFace4_Release(fontface->fontface);
         heap_free(fontface);
     }
 }
@@ -875,36 +875,44 @@ HRESULT factory_get_cached_fontface(IDWriteFactory4 *iface, IDWriteFontFile * co
     return S_FALSE;
 }
 
-void factory_cache_fontface(struct list *fontfaces, IDWriteFontFace4 *fontface)
+struct fontfacecached *factory_cache_fontface(struct list *fontfaces, IDWriteFontFace4 *fontface)
 {
     struct fontfacecached *cached;
 
     /* new cache entry */
     cached = heap_alloc(sizeof(*cached));
     if (!cached)
-        return;
+        return NULL;
 
     cached->fontface = fontface;
     list_add_tail(fontfaces, &cached->entry);
+
+    return cached;
+}
+
+void factory_release_cached_fontface(struct fontfacecached *cached)
+{
+    list_remove(&cached->entry);
+    heap_free(cached);
 }
 
-static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface,
-    DWRITE_FONT_FACE_TYPE req_facetype, UINT32 files_number, IDWriteFontFile* const* font_files,
-    UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face)
+static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface, DWRITE_FONT_FACE_TYPE req_facetype,
+    UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS simulations,
+    IDWriteFontFace **fontface)
 {
     struct dwritefactory *This = impl_from_IDWriteFactory4(iface);
     DWRITE_FONT_FILE_TYPE file_type;
     DWRITE_FONT_FACE_TYPE face_type;
     struct fontface_desc desc;
     struct list *fontfaces;
-    IDWriteFontFace4 *face;
     BOOL is_supported;
     UINT32 count;
     HRESULT hr;
 
-    TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, simulations, font_face);
+    TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index,
+        simulations, fontface);
 
-    *font_face = NULL;
+    *fontface = NULL;
 
     if (!is_face_type_supported(req_facetype))
         return E_INVALIDARG;
@@ -928,9 +936,9 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface,
     if (face_type != req_facetype)
         return DWRITE_E_FILEFORMAT;
 
-    hr = factory_get_cached_fontface(iface, font_files, index, simulations, font_face, &fontfaces);
+    hr = factory_get_cached_fontface(iface, font_files, index, simulations, fontface, &fontfaces);
     if (hr == S_OK)
-        IDWriteFontFace_AddRef(*font_face);
+        IDWriteFontFace_AddRef(*fontface);
 
     if (hr != S_FALSE)
         return hr;
@@ -942,16 +950,7 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface,
     desc.index = index;
     desc.simulations = simulations;
     desc.font_data = NULL;
-    hr = create_fontface(&desc, &face);
-    if (FAILED(hr))
-        return hr;
-
-    factory_cache_fontface(fontfaces, face);
-
-    *font_face = (IDWriteFontFace*)face;
-    IDWriteFontFace_AddRef(*font_face);
-
-    return S_OK;
+    return create_fontface(&desc, fontfaces, (IDWriteFontFace4 **)fontface);
 }
 
 static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory4 *iface, IDWriteRenderingParams **params)
@@ -1083,12 +1082,18 @@ static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory4 *iface, IDW
 static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory4 *iface, IDWriteGdiInterop **gdi_interop)
 {
     struct dwritefactory *This = impl_from_IDWriteFactory4(iface);
+    HRESULT hr = S_OK;
 
     TRACE("(%p)->(%p)\n", This, gdi_interop);
 
-    *gdi_interop = (IDWriteGdiInterop*)&This->interop.IDWriteGdiInterop1_iface;
-    IDWriteGdiInterop_AddRef(*gdi_interop);
-    return S_OK;
+    if (This->gdiinterop)
+        IDWriteGdiInterop1_AddRef(This->gdiinterop);
+    else
+        hr = create_gdiinterop(iface, &This->gdiinterop);
+
+    *gdi_interop = (IDWriteGdiInterop *)This->gdiinterop;
+
+    return hr;
 }
 
 static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory4 *iface, WCHAR const* string,
@@ -1407,11 +1412,10 @@ static HRESULT WINAPI dwritefactory3_GetSystemFontCollection(IDWriteFactory4 *if
     if (check_for_updates)
         FIXME("checking for system font updates not implemented\n");
 
-    if (!This->system_collection)
-        hr = get_system_fontcollection(iface, &This->system_collection);
-
-    if (SUCCEEDED(hr))
+    if (This->system_collection)
         IDWriteFontCollection1_AddRef(This->system_collection);
+    else
+        hr = get_system_fontcollection(iface, &This->system_collection);
 
     *collection = This->system_collection;
 
@@ -1646,7 +1650,7 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP
     factory->localfontfileloader = NULL;
     factory->system_collection = NULL;
     factory->eudc_collection = NULL;
-    gdiinterop_init(&factory->interop, &factory->IDWriteFactory4_iface);
+    factory->gdiinterop = NULL;
     factory->fallback = NULL;
 
     list_init(&factory->collection_loaders);
@@ -1654,6 +1658,21 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP
     list_init(&factory->localfontfaces);
 }
 
+void factory_detach_fontcollection(IDWriteFactory4 *iface, IDWriteFontCollection1 *collection)
+{
+    struct dwritefactory *factory = impl_from_IDWriteFactory4(iface);
+    if (factory->system_collection == collection)
+        factory->system_collection = NULL;
+    IDWriteFactory4_Release(iface);
+}
+
+void factory_detach_gdiinterop(IDWriteFactory4 *iface, IDWriteGdiInterop1 *interop)
+{
+    struct dwritefactory *factory = impl_from_IDWriteFactory4(iface);
+    factory->gdiinterop = NULL;
+    IDWriteFactory4_Release(iface);
+}
+
 HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
 {
     struct dwritefactory *factory;
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 79aebe3ebe..8b16d0e442 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -92,6 +92,15 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
     ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
 }
 
+#define EXPECT_REF_BROKEN(obj,ref,brokenref) _expect_ref_broken((IUnknown*)obj, ref, brokenref, __LINE__)
+static void _expect_ref_broken(IUnknown* obj, ULONG ref, ULONG brokenref, int line)
+{
+    ULONG rc;
+    IUnknown_AddRef(obj);
+    rc = IUnknown_Release(obj);
+    ok_(__FILE__,line)(rc == ref || broken(rc == brokenref), "expected refcount %d, got %d\n", ref, rc);
+}
+
 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size)
 {
     return HeapAlloc(GetProcessHeap(), 0, size);
@@ -847,13 +856,14 @@ static void test_CreateFontFromLOGFONT(void)
     HDC hdc;
     HFONT hfont;
     BOOL exists;
+    ULONG ref;
     int i;
     UINT r;
 
     factory = create_factory();
 
     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
-    EXPECT_HR(hr, S_OK);
+    ok(hr == S_OK, "got %#x\n", hr);
 
     if (0)
         /* null out parameter crashes this call */
@@ -940,6 +950,7 @@ static void test_CreateFontFromLOGFONT(void)
     weight = IDWriteFont_GetWeight(font);
     ok(weight == DWRITE_FONT_WEIGHT_NORMAL || weight == DWRITE_FONT_WEIGHT_BOLD,
         "got %d\n", weight);
+
     IDWriteFont_Release(font);
 
     /* empty or nonexistent face name */
@@ -996,8 +1007,10 @@ static void test_CreateFontFromLOGFONT(void)
     else
         win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n");
 
-    IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteGdiInterop_Release(interop);
+    ok(ref == 0, "interop is not released, %u\n", ref);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory is not released, %u\n", ref);
 }
 
 static void test_CreateBitmapRenderTarget(void)
@@ -1014,6 +1027,7 @@ static void test_CreateBitmapRenderTarget(void)
     HRESULT hr;
     FLOAT pdip;
     SIZE size;
+    ULONG ref;
     HDC hdc;
     int ret;
 
@@ -1257,9 +1271,12 @@ static void test_CreateBitmapRenderTarget(void)
     else
         win_skip("IDWriteBitmapRenderTarget1 is not supported.\n");
 
-    IDWriteBitmapRenderTarget_Release(target);
-    IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteBitmapRenderTarget_Release(target);
+    ok(ref == 0, "render target not released, %u\n", ref);
+    ref = IDWriteGdiInterop_Release(interop);
+    ok(ref == 0, "interop not released, %u\n", ref);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetFontFamily(void)
@@ -1273,6 +1290,7 @@ static void test_GetFontFamily(void)
     IDWriteFactory *factory;
     LOGFONTW logfont;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -1386,7 +1404,8 @@ if (0) /* crashes on native */
     IDWriteFontFamily_Release(family2);
     IDWriteFontFamily_Release(family);
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetFamilyNames(void)
@@ -1400,6 +1419,7 @@ static void test_GetFamilyNames(void)
     WCHAR buffer[100];
     HRESULT hr;
     UINT32 len;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -1482,7 +1502,8 @@ static void test_GetFamilyNames(void)
     IDWriteFontFamily_Release(family);
     IDWriteFont_Release(font);
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_CreateFontFace(void)
@@ -1826,6 +1847,7 @@ static void test_GetMetrics(void)
     HRESULT hr;
     HDC hdc;
     HFONT hfont;
+    ULONG ref;
     int ret;
 
     factory = create_factory();
@@ -1991,6 +2013,7 @@ static void test_GetMetrics(void)
         metrics.strikethroughThickness);
 
     IDWriteFontFile_Release(file);
+    IDWriteFontFace_Release(fontface);
     IDWriteFont_Release(font);
 
     /* test metrics for whole system collection */
@@ -2043,7 +2066,8 @@ static void test_GetMetrics(void)
         IDWriteFontFamily_Release(family);
     }
     IDWriteFontCollection_Release(syscollection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_system_fontcollection(void)
@@ -2058,6 +2082,7 @@ static void test_system_fontcollection(void)
     IDWriteFontFile *file;
     IDWriteFont *font;
     HRESULT hr;
+    ULONG ref;
     UINT32 i;
     BOOL ret;
 
@@ -2131,6 +2156,7 @@ static void test_system_fontcollection(void)
     hr = IDWriteFontFace_GetFiles(fontface, &i, &file);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(file != NULL, "got %p\n", file);
+    IDWriteFontFace_Release(fontface);
 
     hr = IDWriteFontFile_GetLoader(file, &loader);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -2189,8 +2215,10 @@ static void test_system_fontcollection(void)
     else
         win_skip("IDWriteFontCollection1 is not supported.\n");
 
-    IDWriteFontCollection_Release(collection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFontCollection_Release(collection);
+    ok(ref == 0, "collection not released, %u\n", ref);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont)
@@ -2303,13 +2331,14 @@ static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont)
 
 static void test_ConvertFontFaceToLOGFONT(void)
 {
+    IDWriteFontCollection *collection;
     IDWriteGdiInterop *interop;
     IDWriteFontFace *fontface;
     IDWriteFactory *factory;
     LOGFONTW logfont;
     UINT32 count, i;
     HRESULT hr;
-    IDWriteFontCollection *collection;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -2375,8 +2404,8 @@ if (0) /* crashes on native */
             ok(hr == S_OK, "got 0x%08x\n", hr);
 
             sim = IDWriteFontFace_GetSimulations(fontface);
-
             get_logfont_from_font(font, &lf);
+
             ok(logfont.lfWeight == lf.lfWeight, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, "
                 "bold simulation %s\n", wine_dbgstr_w(nameW), logfont.lfWeight, lf.lfWeight, IDWriteFont_GetWeight(font),
                 sim & DWRITE_FONT_SIMULATIONS_BOLD ? "yes" : "no");
@@ -2402,7 +2431,8 @@ if (0) /* crashes on native */
 
     IDWriteFontCollection_Release(collection);
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static HRESULT WINAPI fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
@@ -2447,20 +2477,48 @@ static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl =
     fontfileenumerator_GetCurrentFontFile,
 };
 
+struct collection_loader
+{
+    IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface;
+    LONG ref;
+};
+
+static inline struct collection_loader *impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader *iface)
+{
+    return CONTAINING_RECORD(iface, struct collection_loader, IDWriteFontCollectionLoader_iface);
+}
+
 static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj)
 {
-    *obj = iface;
-    return S_OK;
+    struct collection_loader *loader = impl_from_IDWriteFontCollectionLoader(iface);
+
+    if (IsEqualIID(&IID_IDWriteFontCollectionLoader, riid) ||
+            IsEqualIID(&IID_IUnknown, riid))
+    {
+        *obj = &loader->IDWriteFontCollectionLoader_iface;
+        IDWriteFontCollectionLoader_AddRef(iface);
+        return S_OK;
+    }
+
+    *obj = NULL;
+    return E_NOINTERFACE;
 }
 
 static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface)
 {
-    return 2;
+    struct collection_loader *loader = impl_from_IDWriteFontCollectionLoader(iface);
+    return InterlockedIncrement(&loader->ref);
 }
 
 static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface)
 {
-    return 1;
+    struct collection_loader *loader = impl_from_IDWriteFontCollectionLoader(iface);
+    ULONG ref = InterlockedDecrement(&loader->ref);
+
+    if (!ref)
+        heap_free(loader);
+
+    return ref;
 }
 
 static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory, const void *key,
@@ -2478,12 +2536,20 @@ static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervt
     fontcollectionloader_CreateEnumeratorFromKey
 };
 
+static IDWriteFontCollectionLoader *create_collection_loader(void)
+{
+    struct collection_loader *loader = heap_alloc(sizeof(*loader));
+
+    loader->IDWriteFontCollectionLoader_iface.lpVtbl = &dwritefontcollectionloadervtbl;
+    loader->ref = 1;
+
+    return &loader->IDWriteFontCollectionLoader_iface;
+}
+
 static void test_CustomFontCollection(void)
 {
     static const WCHAR fontnameW[] = {'w','i','n','e','_','t','e','s','t',0};
-    IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl };
-    IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl };
-    IDWriteFontCollectionLoader collection3 = { &dwritefontcollectionloadervtbl };
+    IDWriteFontCollectionLoader *loader, *loader2, *loader3;
     IDWriteFontCollection *font_collection = NULL;
     static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
     struct test_fontcollectionloader resource_collection = { { &resourcecollectionloadervtbl }, &rloader };
@@ -2497,37 +2563,53 @@ static void test_CustomFontCollection(void)
     BOOL exists;
     HRESULT hr;
     HRSRC font;
+    ULONG ref;
 
     factory = create_factory();
 
+    loader = create_collection_loader();
+    loader2 = create_collection_loader();
+    loader3 = create_collection_loader();
+
     hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
 
     hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
 
-    hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
+    EXPECT_REF(loader, 1);
+    EXPECT_REF(loader2, 1);
+
+    hr = IDWriteFactory_RegisterFontCollectionLoader(factory, loader);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-    hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2);
+    hr = IDWriteFactory_RegisterFontCollectionLoader(factory, loader2);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-    hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection);
+    hr = IDWriteFactory_RegisterFontCollectionLoader(factory, loader);
     ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr);
 
+    EXPECT_REF(loader, 2);
+    EXPECT_REF(loader2, 2);
+
     hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    /* Loader wasn't registered. */
     font_collection = (void*)0xdeadbeef;
-    hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection3, "Billy", 6, &font_collection);
+    hr = IDWriteFactory_CreateCustomFontCollection(factory, loader3, "Billy", 6, &font_collection);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
     ok(font_collection == NULL, "got %p\n", font_collection);
 
-    hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection, "Billy", 6, &font_collection);
+    EXPECT_REF(factory, 1);
+    hr = IDWriteFactory_CreateCustomFontCollection(factory, loader, "Billy", 6, &font_collection);
     ok(hr == S_OK, "got 0x%08x\n", hr);
+todo_wine
+    EXPECT_REF(factory, 1);
+    EXPECT_REF(loader, 2);
     IDWriteFontCollection_Release(font_collection);
 
-    hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection2, "Billy", 6, &font_collection);
+    hr = IDWriteFactory_CreateCustomFontCollection(factory, loader2, "Billy", 6, &font_collection);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     IDWriteFontCollection_Release(font_collection);
 
@@ -2542,6 +2624,7 @@ static void test_CustomFontCollection(void)
     hr = IDWriteFactory_CreateCustomFontCollection(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface,
         &font, sizeof(HRSRC), &font_collection);
     ok(hr == S_OK, "got 0x%08x\n",hr);
+    EXPECT_REF(font_collection, 1);
 
     index = 1;
     exists = FALSE;
@@ -2626,18 +2709,23 @@ static void test_CustomFontCollection(void)
     IDWriteFontFamily_Release(family);
     IDWriteFontCollection_Release(font_collection);
 
-    hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
+    hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, loader);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-    hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection);
+    hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, loader);
     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
-    hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2);
+    hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, loader2);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    IDWriteFactory_Release(factory);
+    IDWriteFontCollectionLoader_Release(loader);
+    IDWriteFontCollectionLoader_Release(loader2);
+    IDWriteFontCollectionLoader_Release(loader3);
+
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj)
@@ -2696,6 +2784,7 @@ static void test_CreateCustomFontFileReference(void)
     const void *key;
     UINT32 key_size;
     WCHAR *path;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
 
@@ -2854,8 +2943,10 @@ if (face2) {
     hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    IDWriteFactory_Release(factory2);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory2);
+    ok(ref == 0, "factory not released, %u\n", ref);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -2870,6 +2961,7 @@ static void test_CreateFontFileReference(void)
     IDWriteFontFace *fface = NULL;
     IDWriteFactory *factory;
     WCHAR *path;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
     factory = create_factory();
@@ -2898,7 +2990,8 @@ static void test_CreateFontFileReference(void)
 
     IDWriteFontFace_Release(fface);
     IDWriteFontFile_Release(ffile);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 
     DELETE_FONTFILE(path);
 }
@@ -2908,6 +3001,7 @@ static void test_shared_isolated(void)
     IDWriteFactory *isolated, *isolated2;
     IDWriteFactory *shared, *shared2;
     HRESULT hr;
+    ULONG ref;
 
     /* invalid type */
     shared = NULL;
@@ -2953,8 +3047,10 @@ static void test_shared_isolated(void)
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
 
-    IDWriteFactory_Release(isolated);
-    IDWriteFactory_Release(isolated2);
+    ref = IDWriteFactory_Release(isolated);
+    ok(ref == 0, "factory not released, %u\n", ref);
+    ref = IDWriteFactory_Release(isolated2);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetUnicodeRanges(void)
@@ -2967,6 +3063,7 @@ static void test_GetUnicodeRanges(void)
     UINT32 count;
     HRESULT hr;
     HRSRC font;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3021,7 +3118,8 @@ static void test_GetUnicodeRanges(void)
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     IDWriteFontFace1_Release(fontface1);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetFontFromFontFace(void)
@@ -3034,6 +3132,7 @@ static void test_GetFontFromFontFace(void)
     IDWriteFontFile *file;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3093,7 +3192,8 @@ static void test_GetFontFromFontFace(void)
     IDWriteFont_Release(font2);
     IDWriteFontFamily_Release(family);
     IDWriteFontCollection_Release(collection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -3105,6 +3205,7 @@ static void test_GetFirstMatchingFont(void)
     IDWriteFont *font, *font2;
     IDWriteFactory *factory;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3147,7 +3248,8 @@ static void test_GetFirstMatchingFont(void)
     IDWriteFont_Release(font);
 
     IDWriteFontCollection_Release(collection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetMatchingFonts(void)
@@ -3158,6 +3260,7 @@ static void test_GetMatchingFonts(void)
     IDWriteFontList *fontlist, *fontlist2;
     IDWriteFontList1 *fontlist1;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3234,7 +3337,8 @@ static void test_GetMatchingFonts(void)
     IDWriteFontFamily_Release(family);
 
     IDWriteFontCollection_Release(collection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetInformationalStrings(void)
@@ -3246,6 +3350,7 @@ static void test_GetInformationalStrings(void)
     IDWriteFont *font;
     BOOL exists;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3289,7 +3394,8 @@ static void test_GetInformationalStrings(void)
     IDWriteFont_Release(font);
     IDWriteFontFamily_Release(family);
     IDWriteFontCollection_Release(collection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetGdiInterop(void)
@@ -3299,6 +3405,7 @@ static void test_GetGdiInterop(void)
     IDWriteFont *font;
     LOGFONTW logfont;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3337,7 +3444,8 @@ static void test_GetGdiInterop(void)
 
     IDWriteGdiInterop_Release(interop2);
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_CreateFontFaceFromHdc(void)
@@ -3348,6 +3456,7 @@ static void test_CreateFontFaceFromHdc(void)
     HFONT hfont, oldhfont;
     LOGFONTW logfont;
     HRESULT hr;
+    ULONG ref;
     HDC hdc;
 
     factory = create_factory();
@@ -3380,7 +3489,8 @@ static void test_CreateFontFaceFromHdc(void)
     DeleteDC(hdc);
 
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetSimulations(void)
@@ -3392,6 +3502,7 @@ static void test_GetSimulations(void)
     IDWriteFont *font;
     LOGFONTW logfont;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3437,7 +3548,8 @@ static void test_GetSimulations(void)
     IDWriteFont_Release(font);
 
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetFaceNames(void)
@@ -3454,6 +3566,7 @@ static void test_GetFaceNames(void)
     WCHAR buffW[255];
     BOOL exists;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3506,7 +3619,8 @@ static void test_GetFaceNames(void)
 
     IDWriteFont_Release(font);
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 struct local_refkey
@@ -3531,6 +3645,7 @@ static void test_TryGetFontTable(void)
     UINT32 size, len;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
 
@@ -3596,7 +3711,8 @@ static void test_TryGetFontTable(void)
 
     IDWriteFontFace_Release(fontface);
     IDWriteFontFile_Release(file);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -3611,6 +3727,7 @@ static void test_ConvertFontToLOGFONT(void)
     UINT32 i, count;
     BOOL system;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     factory2 = create_factory();
@@ -3716,7 +3833,8 @@ if (0) { /* crashes on native */
     IDWriteFontFamily_Release(family);
     IDWriteFont_Release(font);
     IDWriteGdiInterop_Release(interop);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_CreateStreamFromKey(void)
@@ -3731,6 +3849,7 @@ static void test_CreateStreamFromKey(void)
     void *key;
     UINT32 size;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3775,7 +3894,8 @@ static void test_CreateStreamFromKey(void)
     IDWriteFontFile_Release(file);
 
     IDWriteLocalFontFileLoader_Release(localloader);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -3792,6 +3912,7 @@ static void test_ReadFileFragment(void)
     UINT32 size;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3854,7 +3975,8 @@ static void test_ReadFileFragment(void)
     IDWriteFontFile_Release(file);
     IDWriteFontFileStream_Release(stream);
     IDWriteLocalFontFileLoader_Release(localloader);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -3868,6 +3990,7 @@ static void test_GetDesignGlyphMetrics(void)
     UINT32 codepoint;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -3905,7 +4028,8 @@ static void test_GetDesignGlyphMetrics(void)
     ok(metrics[1].advanceWidth == 0, "got %d\n", metrics[1].advanceWidth);
 
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -3917,6 +4041,7 @@ static void test_IsMonospacedFont(void)
     UINT32 index;
     BOOL exists;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
@@ -3960,11 +4085,14 @@ static void test_IsMonospacedFont(void)
         }
         else
             win_skip("IsMonospacedFont() is not supported.\n");
+
+        IDWriteFont_Release(font);
     }
     else
         skip("Courier New font not found.\n");
 
-    IDWriteFontCollection_Release(collection);
+    ref = IDWriteFontCollection_Release(collection);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetDesignGlyphAdvances(void)
@@ -3975,6 +4103,7 @@ static void test_GetDesignGlyphAdvances(void)
     IDWriteFontFile *file;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -4017,7 +4146,8 @@ static void test_GetDesignGlyphAdvances(void)
         win_skip("GetDesignGlyphAdvances() is not supported.\n");
 
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -4032,6 +4162,7 @@ static void test_GetGlyphRunOutline(void)
     UINT16 glyphs[2];
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
     factory = create_factory();
@@ -4155,8 +4286,9 @@ static void test_GetGlyphRunOutline(void)
     ok(hr == S_OK, "got 0x%08x\n", hr);
     CHECK_CALLED(setfillmode);
 
-    IDWriteFactory_Release(factory);
     IDWriteFontFace_Release(face);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetEudcFontCollection(void)
@@ -4165,6 +4297,7 @@ static void test_GetEudcFontCollection(void)
     IDWriteFactory1 *factory1;
     IDWriteFactory *factory;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -4183,7 +4316,8 @@ static void test_GetEudcFontCollection(void)
     IDWriteFontCollection_Release(coll);
     IDWriteFontCollection_Release(coll2);
 
-    IDWriteFactory1_Release(factory1);
+    ref = IDWriteFactory1_Release(factory1);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_GetCaretMetrics(void)
@@ -4197,6 +4331,7 @@ static void test_GetCaretMetrics(void)
     IDWriteFont *font;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
     factory = create_factory();
@@ -4212,7 +4347,8 @@ static void test_GetCaretMetrics(void)
     IDWriteFontFace_Release(fontface);
     if (hr != S_OK) {
         win_skip("GetCaretMetrics() is not supported.\n");
-        IDWriteFactory_Release(factory);
+        ref = IDWriteFactory_Release(factory);
+        ok(ref == 0, "factory not released, %u\n", ref);
         DELETE_FONTFILE(path);
         return;
     }
@@ -4260,7 +4396,8 @@ static void test_GetCaretMetrics(void)
     ok(caret.offset == 0, "got %d\n", caret.offset);
     IDWriteFontFace1_Release(fontface1);
 
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -4272,6 +4409,7 @@ static void test_GetGlyphCount(void)
     UINT16 count;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
     factory = create_factory();
@@ -4287,7 +4425,8 @@ static void test_GetGlyphCount(void)
     ok(count == 7, "got %u\n", count);
 
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -4299,6 +4438,7 @@ static void test_GetKerningPairAdjustments(void)
     IDWriteFontFile *file;
     WCHAR *path;
     HRESULT hr;
+    ULONG ref;
 
     path = create_testfontfile(test_fontfile);
     factory = create_factory();
@@ -4331,7 +4471,8 @@ static void test_GetKerningPairAdjustments(void)
         win_skip("GetKerningPairAdjustments() is not supported.\n");
 
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
     DELETE_FONTFILE(path);
 }
 
@@ -4344,6 +4485,7 @@ static void test_CreateRenderingParams(void)
     IDWriteFactory3 *factory3;
     IDWriteFactory *factory;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -4406,7 +4548,8 @@ static void test_CreateRenderingParams(void)
     else
         win_skip("IDWriteRenderingParams3 not supported.\n");
 
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_CreateGlyphRunAnalysis(void)
@@ -4432,6 +4575,7 @@ static void test_CreateGlyphRunAnalysis(void)
     DWRITE_GLYPH_METRICS metrics;
     DWRITE_FONT_METRICS fm;
     DWRITE_MATRIX m;
+    ULONG ref;
     int i;
 
     factory = create_factory();
@@ -4717,7 +4861,8 @@ static void test_CreateGlyphRunAnalysis(void)
     IDWriteGlyphRunAnalysis_Release(analysis);
 
     IDWriteFontFace_Release(face);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 #define round(x) ((int)floor((x) + 0.5))
@@ -4912,7 +5057,7 @@ static void get_expected_metrics(IDWriteFontFace *fontface, struct compatmetrics
     ok(hr == S_OK, "got %08x\n", hr);
 }
 
-static void test_GetGdiCompatibleMetrics_face(IDWriteFontFace *face)
+static void test_gdicompat_metrics(IDWriteFontFace *face)
 {
     IDWriteFontFace1 *fontface1 = NULL;
     HRESULT hr;
@@ -5049,6 +5194,7 @@ static void test_GetGdiCompatibleMetrics(void)
     IDWriteFont *font;
     IDWriteFontFace *fontface;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -5056,7 +5202,7 @@ static void test_GetGdiCompatibleMetrics(void)
     hr = IDWriteFont_CreateFontFace(font, &fontface);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     IDWriteFont_Release(font);
-    test_GetGdiCompatibleMetrics_face(fontface);
+    test_gdicompat_metrics(fontface);
     IDWriteFontFace_Release(fontface);
 
     font = get_font(factory, arialW, DWRITE_FONT_STYLE_NORMAL);
@@ -5068,11 +5214,12 @@ static void test_GetGdiCompatibleMetrics(void)
         ok(hr == S_OK, "got 0x%08x\n", hr);
         IDWriteFont_Release(font);
 
-        test_GetGdiCompatibleMetrics_face(fontface);
+        test_gdicompat_metrics(fontface);
         IDWriteFontFace_Release(fontface);
     }
 
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void get_expected_panose(IDWriteFont1 *font, DWRITE_PANOSE *panose)
@@ -5108,18 +5255,21 @@ static void test_GetPanose(void)
     IDWriteFont *font;
     UINT count, i;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
 
-    hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1);
+    hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void **)&font1);
     IDWriteFont_Release(font);
 
     if (FAILED(hr)) {
-        IDWriteFactory_Release(factory);
+        ref = IDWriteFactory_Release(factory);
+        ok(ref == 0, "factory not released, %u\n", ref);
         win_skip("GetPanose() is not supported.\n");
         return;
     }
+    IDWriteFont1_Release(font1);
 
     hr = IDWriteFactory_GetSystemFontCollection(factory, &syscollection, FALSE);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -5191,7 +5341,8 @@ static void test_GetPanose(void)
     }
 
     IDWriteFontCollection_Release(syscollection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static INT32 get_gdi_font_advance(HDC hdc, FLOAT emsize)
@@ -5231,6 +5382,7 @@ static void test_GetGdiCompatibleGlyphAdvances(void)
     FLOAT emsize;
     DWRITE_FONT_METRICS1 fm;
     INT32 advance;
+    ULONG ref;
 
     factory = create_factory();
     font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
@@ -5239,11 +5391,12 @@ static void test_GetGdiCompatibleGlyphAdvances(void)
     ok(hr == S_OK, "got 0x%08x\n", hr);
     IDWriteFont_Release(font);
 
-    hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
+    hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void **)&fontface1);
     IDWriteFontFace_Release(fontface);
 
     if (hr != S_OK) {
-        IDWriteFactory_Release(factory);
+        ref = IDWriteFactory_Release(factory);
+        ok(ref == 0, "factory not released, %u\n", ref);
         win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
         return;
     }
@@ -5301,7 +5454,9 @@ static void test_GetGdiCompatibleGlyphAdvances(void)
 
     DeleteObject(hdc);
 
-    IDWriteFactory_Release(factory);
+    IDWriteFontFace1_Release(fontface1);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static WORD get_gasp_flags(IDWriteFontFace *fontface, FLOAT emsize, FLOAT ppdip)
@@ -5434,6 +5589,7 @@ static void test_GetRecommendedRenderingMode(void)
     IDWriteFactory *factory;
     FLOAT emsize;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     fontface = create_fontface(factory);
@@ -5746,7 +5902,8 @@ static void test_GetRecommendedRenderingMode(void)
     if (fontface1)
         IDWriteFontFace1_Release(fontface1);
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static inline BOOL float_eq(FLOAT left, FLOAT right)
@@ -5785,6 +5942,7 @@ static void test_GetAlphaBlendParams(void)
     UINT16 glyph;
     UINT32 ch, i;
     HRESULT hr;
+    ULONG ref;
     BOOL ret;
 
     factory = create_factory();
@@ -5854,7 +6012,8 @@ static void test_GetAlphaBlendParams(void)
 
     IDWriteRenderingParams_Release(params);
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_CreateAlphaTexture(void)
@@ -5871,6 +6030,7 @@ static void test_CreateAlphaTexture(void)
     FLOAT advance;
     UINT16 glyph;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     fontface = create_fontface(factory);
@@ -5995,7 +6155,8 @@ static void test_CreateAlphaTexture(void)
 
     IDWriteGlyphRunAnalysis_Release(analysis);
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_IsSymbolFont(void)
@@ -6006,6 +6167,7 @@ static void test_IsSymbolFont(void)
     IDWriteFactory *factory;
     IDWriteFont *font;
     HRESULT hr;
+    ULONG ref;
     BOOL ret;
 
     factory = create_factory();
@@ -6037,9 +6199,11 @@ static void test_IsSymbolFont(void)
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ret = IDWriteFontFace_IsSymbolFont(fontface);
     ok(ret, "got %d\n", ret);
+    IDWriteFontFace_Release(fontface);
     IDWriteFont_Release(font);
 
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 struct CPAL_Header_0
@@ -6064,6 +6228,7 @@ static void test_GetPaletteEntries(void)
     const struct CPAL_Header_0 *cpal_header;
     HRESULT hr;
     BOOL exists;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -6072,7 +6237,8 @@ static void test_GetPaletteEntries(void)
     hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2);
     IDWriteFontFace_Release(fontface);
     if (hr != S_OK) {
-        IDWriteFactory_Release(factory);
+        ref = IDWriteFactory_Release(factory);
+        ok(ref == 0, "factory not released, %u\n", ref);
         win_skip("GetPaletteEntries() is not supported.\n");
         return;
     }
@@ -6084,7 +6250,8 @@ static void test_GetPaletteEntries(void)
     /* Segoe UI Emoji, with color support */
     font = get_font(factory, emojiW, DWRITE_FONT_STYLE_NORMAL);
     if (!font) {
-        IDWriteFactory_Release(factory);
+        ref = IDWriteFactory_Release(factory);
+        ok(ref == 0, "factory not released, %u\n", ref);
         skip("Segoe UI Emoji font not found.\n");
         return;
     }
@@ -6138,7 +6305,8 @@ static void test_GetPaletteEntries(void)
         "got wrong color %.2fx%.2fx%.2fx%.2f\n", color.r, color.g, color.b, color.a);
 
     IDWriteFontFace2_Release(fontface2);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_TranslateColorGlyphRun(void)
@@ -6155,6 +6323,7 @@ static void test_TranslateColorGlyphRun(void)
     UINT16 glyphs[2];
     BOOL hasrun;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -6282,7 +6451,8 @@ static void test_TranslateColorGlyphRun(void)
 
     IDWriteFontFace2_Release(fontface2);
     IDWriteFontFace_Release(fontface);
-    IDWriteFactory2_Release(factory2);
+    ref = IDWriteFactory2_Release(factory2);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_HasCharacter(void)
@@ -6292,6 +6462,7 @@ static void test_HasCharacter(void)
     IDWriteFont3 *font3;
     IDWriteFont *font;
     HRESULT hr;
+    ULONG ref;
     BOOL ret;
 
     factory = create_factory();
@@ -6315,7 +6486,8 @@ static void test_HasCharacter(void)
         win_skip("IDWriteFont3 is not supported.\n");
 
     IDWriteFont_Release(font);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_CreateFontFaceReference(void)
@@ -6328,6 +6500,7 @@ static void test_CreateFontFaceReference(void)
     IDWriteFactory *factory;
     IDWriteFont3 *font3;
     IDWriteFont *font;
+    ULONG refcount;
     UINT32 index;
     WCHAR *path;
     HRESULT hr;
@@ -6482,7 +6655,8 @@ if (hr == S_OK) {
     IDWriteFontFace3_Release(fontface);
     IDWriteFont3_Release(font3);
 
-    IDWriteFactory3_Release(factory3);
+    refcount = IDWriteFactory3_Release(factory3);
+    ok(refcount == 0, "factory not released, %u\n", refcount);
     DELETE_FONTFILE(path);
 }
 
@@ -6533,6 +6707,7 @@ static void test_GetFontSignature(void)
     FONTSIGNATURE fontsig;
     UINT count, i;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -6602,7 +6777,8 @@ static void test_GetFontSignature(void)
 
     IDWriteGdiInterop1_Release(interop1);
     IDWriteFontCollection_Release(syscollection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_font_properties(void)
@@ -6613,6 +6789,7 @@ static void test_font_properties(void)
     DWRITE_FONT_STYLE style;
     IDWriteFont *font;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
 
@@ -6635,7 +6812,8 @@ static void test_font_properties(void)
     }
 
     IDWriteFont_Release(font);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static BOOL has_vertical_glyph_variants(IDWriteFontFace1 *fontface)
@@ -6724,6 +6902,7 @@ static void test_HasVerticalGlyphVariants(void)
     IDWriteFactory *factory;
     UINT32 count, i;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     fontface = create_fontface(factory);
@@ -6781,7 +6960,8 @@ static void test_HasVerticalGlyphVariants(void)
     }
 
     IDWriteFontCollection_Release(syscollection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_HasKerningPairs(void)
@@ -6792,6 +6972,7 @@ static void test_HasKerningPairs(void)
     IDWriteFactory *factory;
     UINT32 count, i;
     HRESULT hr;
+    ULONG ref;
 
     factory = create_factory();
     fontface = create_fontface(factory);
@@ -6855,7 +7036,8 @@ static void test_HasKerningPairs(void)
     }
 
     IDWriteFontCollection_Release(syscollection);
-    IDWriteFactory_Release(factory);
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 static void test_ComputeGlyphOrigins(void)
@@ -6869,6 +7051,7 @@ static void test_ComputeGlyphOrigins(void)
     UINT16 glyphs[2];
     FLOAT advances[2];
     DWRITE_MATRIX m;
+    ULONG ref;
 
     factory = create_factory();
     hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory4, (void **)&factory4);
@@ -6919,7 +7102,165 @@ static void test_ComputeGlyphOrigins(void)
     ok(origins[0].x == 123.0f && origins[0].y == 321.0f, "origins[0] %f,%f\n", origins[0].x, origins[0].y);
     ok(origins[1].x == 133.0f && origins[1].y == 321.0f, "origins[1] %f,%f\n", origins[1].x, origins[1].y);
 
-    IDWriteFactory4_Release(factory4);
+    ref = IDWriteFactory4_Release(factory4);
+    ok(ref == 0, "factory not released, %u\n", ref);
+}
+
+static void test_object_lifetime(void)
+{
+    IDWriteFontCollection *collection, *collection2;
+    IDWriteFontList *fontlist, *fontlist2;
+    IDWriteGdiInterop *interop, *interop2;
+    IDWriteFontFamily *family, *family2;
+    IDWriteFontFace *fontface;
+    IDWriteFont *font, *font2;
+    IDWriteFactory *factory;
+    HRESULT hr;
+    ULONG ref;
+
+    factory = create_factory();
+    EXPECT_REF(factory, 1);
+
+    /* system collection takes factory reference */
+    hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(collection, 1);
+    EXPECT_REF(factory, 2);
+
+    hr = IDWriteFactory_GetSystemFontCollection(factory, &collection2, FALSE);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(collection2 == collection, "expected same collection\n");
+
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    IDWriteFontCollection_Release(collection2);
+
+    IDWriteFontCollection_AddRef(collection);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+    IDWriteFontCollection_Release(collection);
+
+    EXPECT_REF(collection, 1);
+
+    /* family takes collection reference */
+    hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(family, 1);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family2);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(family2, 1);
+    EXPECT_REF(collection, 3);
+    EXPECT_REF(factory, 2);
+
+    IDWriteFontFamily_Release(family2);
+
+    EXPECT_REF(family, 1);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    /* font takes family reference */
+    hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL,
+        DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(family, 2);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    hr = IDWriteFont_GetFontFamily(font, &family2);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(family2 == family, "unexpected family pointer\n");
+    IDWriteFontFamily_Release(family2);
+
+    EXPECT_REF(font, 1);
+    EXPECT_REF(factory, 2);
+
+    /* Fontface takes factory reference and nothing else. */
+    hr = IDWriteFont_CreateFontFace(font, &fontface);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(font, 1);
+    EXPECT_REF_BROKEN(fontface, 1, 2);
+    EXPECT_REF(family, 2);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF_BROKEN(factory, 3, 2);
+
+    /* get font from fontface */
+    hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(font, 1);
+    EXPECT_REF(font2, 1);
+    EXPECT_REF_BROKEN(fontface, 1, 2);
+    EXPECT_REF(family, 2);
+    EXPECT_REF(collection, 3);
+    EXPECT_REF_BROKEN(factory, 3, 2);
+
+    IDWriteFont_Release(font2);
+    IDWriteFontFace_Release(fontface);
+
+    EXPECT_REF(font, 1);
+    EXPECT_REF(family, 2);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    IDWriteFont_Release(font);
+
+    EXPECT_REF(family, 1);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    /* Matching fonts list takes family reference. */
+    hr = IDWriteFontFamily_GetMatchingFonts(family, DWRITE_FONT_WEIGHT_NORMAL,
+        DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &fontlist);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    EXPECT_REF(family, 2);
+    EXPECT_REF(collection, 2);
+    EXPECT_REF(factory, 2);
+
+    hr = IDWriteFontFamily_GetMatchingFonts(family, DWRITE_FONT_WEIGHT_NORMAL,
+        DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &fontlist2);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(fontlist2 != fontlist, "unexpected font list\n");
+    IDWriteFontList_Release(fontlist2);
+
+    IDWriteFontList_Release(fontlist);
+
+    IDWriteFontFamily_Release(family);
+    EXPECT_REF(collection, 1);
+
+    EXPECT_REF(factory, 2);
+    ref = IDWriteFontCollection_Release(collection);
+    ok(ref == 0, "collection not released, %u\n", ref);
+    EXPECT_REF(factory, 1);
+
+    /* GDI interop object takes factory reference */
+    hr = IDWriteFactory_GetGdiInterop(factory, &interop);
+    ok(hr == S_OK, "got %#x\n", hr);
+    EXPECT_REF(interop, 1);
+    EXPECT_REF(factory, 2);
+
+    hr = IDWriteFactory_GetGdiInterop(factory, &interop2);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(interop == interop2, "got unexpected interop pointer\n");
+
+    EXPECT_REF(interop, 2);
+    EXPECT_REF(factory, 2);
+
+    IDWriteGdiInterop_Release(interop2);
+    ref = IDWriteGdiInterop_Release(interop);
+    ok(ref == 0, "interop not released, %u\n", ref);
+
+    ref = IDWriteFactory_Release(factory);
+    ok(ref == 0, "factory not released, %u\n", ref);
 }
 
 START_TEST(font)
@@ -6931,6 +7272,7 @@ START_TEST(font)
         return;
     }
 
+    test_object_lifetime();
     test_CreateFontFromLOGFONT();
     test_CreateBitmapRenderTarget();
     test_GetFontFamily();
-- 
2.11.0




More information about the wine-patches mailing list