Use COM_DECLSPEC_NOTHROW STDMETHODIMP

Use STDMETHODIMP because it's the right thing to do, use
COM_DECLSPEC_NOTHROW because STDMETHOD uses it but STDMETHODIMP does
not, leading to warnings from clang and maybe also from msvc, see
https://developercommunity.visualstudio.com/content/problem/325764/msvc-1582-generates-warning-c4986-in-atl-header-fi.html

This also removes SkBlockComRef, since even WRL has abandoned the
similar RemoveIUnknown. These classes were helpful in the transition to
using smart pointers, but are incompatible with final implementations.

Change-Id: I53a618ee629af638d9d8625ccd5acb0db6529950
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/233988
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/src/ports/SkFontMgr_win_dw.cpp b/src/ports/SkFontMgr_win_dw.cpp
index 4387ce6..acf5919 100644
--- a/src/ports/SkFontMgr_win_dw.cpp
+++ b/src/ports/SkFontMgr_win_dw.cpp
@@ -22,6 +22,7 @@
 #include "src/utils/win/SkDWrite.h"
 #include "src/utils/win/SkDWriteFontFileStream.h"
 #include "src/utils/win/SkHRESULT.h"
+#include "src/utils/win/SkObjBase.h"
 #include "src/utils/win/SkTScopedComPtr.h"
 
 #include <dwrite.h>
@@ -33,15 +34,15 @@
 class StreamFontFileLoader : public IDWriteFontFileLoader {
 public:
     // IUnknown methods
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
-    virtual ULONG STDMETHODCALLTYPE AddRef();
-    virtual ULONG STDMETHODCALLTYPE Release();
+    SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
+    SK_STDMETHODIMP_(ULONG) AddRef() override;
+    SK_STDMETHODIMP_(ULONG) Release() override;
 
     // IDWriteFontFileLoader methods
-    virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
+    SK_STDMETHODIMP CreateStreamFromKey(
         void const* fontFileReferenceKey,
         UINT32 fontFileReferenceKeySize,
-        IDWriteFontFileStream** fontFileStream);
+        IDWriteFontFileStream** fontFileStream) override;
 
     // Takes ownership of stream.
     static HRESULT Create(std::unique_ptr<SkStreamAsset> stream,
@@ -53,18 +54,17 @@
         return S_OK;
     }
 
-    std::unique_ptr<SkStreamAsset> fStream;
-
 private:
     StreamFontFileLoader(std::unique_ptr<SkStreamAsset> stream)
         : fStream(std::move(stream)), fRefCount(1)
     {}
     virtual ~StreamFontFileLoader() { }
 
+    std::unique_ptr<SkStreamAsset> fStream;
     ULONG fRefCount;
 };
 
-HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
+SK_STDMETHODIMP StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
         *ppvObject = this;
         AddRef();
@@ -75,11 +75,11 @@
     }
 }
 
-ULONG StreamFontFileLoader::AddRef() {
+SK_STDMETHODIMP_(ULONG) StreamFontFileLoader::AddRef() {
     return InterlockedIncrement(&fRefCount);
 }
 
-ULONG StreamFontFileLoader::Release() {
+SK_STDMETHODIMP_(ULONG) StreamFontFileLoader::Release() {
     ULONG newCount = InterlockedDecrement(&fRefCount);
     if (0 == newCount) {
         delete this;
@@ -87,7 +87,7 @@
     return newCount;
 }
 
-HRESULT StreamFontFileLoader::CreateStreamFromKey(
+SK_STDMETHODIMP StreamFontFileLoader::CreateStreamFromKey(
     void const* fontFileReferenceKey,
     UINT32 fontFileReferenceKeySize,
     IDWriteFontFileStream** fontFileStream)
@@ -103,13 +103,13 @@
 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
 public:
     // IUnknown methods
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
-    virtual ULONG STDMETHODCALLTYPE AddRef();
-    virtual ULONG STDMETHODCALLTYPE Release();
+    SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
+    SK_STDMETHODIMP_(ULONG) AddRef() override;
+    SK_STDMETHODIMP_(ULONG) Release() override;
 
     // IDWriteFontFileEnumerator methods
-    virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
-    virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
+    SK_STDMETHODIMP MoveNext(BOOL* hasCurrentFile) override;
+    SK_STDMETHODIMP GetCurrentFontFile(IDWriteFontFile** fontFile) override;
 
     static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
                           StreamFontFileEnumerator** streamFontFileEnumerator) {
@@ -140,7 +140,7 @@
     , fHasNext(true)
 { }
 
-HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
+SK_STDMETHODIMP StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
         *ppvObject = this;
         AddRef();
@@ -151,11 +151,11 @@
     }
 }
 
-ULONG StreamFontFileEnumerator::AddRef() {
+SK_STDMETHODIMP_(ULONG) StreamFontFileEnumerator::AddRef() {
     return InterlockedIncrement(&fRefCount);
 }
 
-ULONG StreamFontFileEnumerator::Release() {
+SK_STDMETHODIMP_(ULONG) StreamFontFileEnumerator::Release() {
     ULONG newCount = InterlockedDecrement(&fRefCount);
     if (0 == newCount) {
         delete this;
@@ -163,7 +163,7 @@
     return newCount;
 }
 
-HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
+SK_STDMETHODIMP StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
     *hasCurrentFile = FALSE;
 
     if (!fHasNext) {
@@ -182,7 +182,7 @@
     return S_OK;
 }
 
-HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
+SK_STDMETHODIMP StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
     if (fCurrentFile.get() == nullptr) {
         *fontFile = nullptr;
         return E_FAIL;
@@ -197,16 +197,16 @@
 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
 public:
     // IUnknown methods
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
-    virtual ULONG STDMETHODCALLTYPE AddRef();
-    virtual ULONG STDMETHODCALLTYPE Release();
+    SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
+    SK_STDMETHODIMP_(ULONG) AddRef() override;
+    SK_STDMETHODIMP_(ULONG) Release() override;
 
     // IDWriteFontCollectionLoader methods
-    virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
+    SK_STDMETHODIMP CreateEnumeratorFromKey(
         IDWriteFactory* factory,
         void const* collectionKey,
         UINT32 collectionKeySize,
-        IDWriteFontFileEnumerator** fontFileEnumerator);
+        IDWriteFontFileEnumerator** fontFileEnumerator) override;
 
     static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
                           StreamFontCollectionLoader** streamFontCollectionLoader) {
@@ -227,7 +227,7 @@
     SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
 };
 
-HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
+SK_STDMETHODIMP StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
         *ppvObject = this;
         AddRef();
@@ -238,11 +238,11 @@
     }
 }
 
-ULONG StreamFontCollectionLoader::AddRef() {
+SK_STDMETHODIMP_(ULONG) StreamFontCollectionLoader::AddRef() {
     return InterlockedIncrement(&fRefCount);
 }
 
-ULONG StreamFontCollectionLoader::Release() {
+SK_STDMETHODIMP_(ULONG) StreamFontCollectionLoader::Release() {
     ULONG newCount = InterlockedDecrement(&fRefCount);
     if (0 == newCount) {
         delete this;
@@ -250,7 +250,7 @@
     return newCount;
 }
 
-HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
+SK_STDMETHODIMP StreamFontCollectionLoader::CreateEnumeratorFromKey(
     IDWriteFactory* factory,
     void const* collectionKey,
     UINT32 collectionKeySize,
@@ -520,10 +520,34 @@
         : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character), fResolvedTypeface(nullptr) {
     }
 
-    virtual ~FontFallbackRenderer() { }
+    // IUnknown methods
+    SK_STDMETHODIMP QueryInterface(IID const& riid, void** ppvObject) override {
+        if (__uuidof(IUnknown) == riid ||
+            __uuidof(IDWritePixelSnapping) == riid ||
+            __uuidof(IDWriteTextRenderer) == riid)
+        {
+            *ppvObject = this;
+            this->AddRef();
+            return S_OK;
+        }
+        *ppvObject = nullptr;
+        return E_FAIL;
+    }
+
+    SK_STDMETHODIMP_(ULONG) AddRef() override {
+        return InterlockedIncrement(&fRefCount);
+    }
+
+    SK_STDMETHODIMP_(ULONG) Release() override {
+        ULONG newCount = InterlockedDecrement(&fRefCount);
+        if (0 == newCount) {
+            delete this;
+        }
+        return newCount;
+    }
 
     // IDWriteTextRenderer methods
-    virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
+    SK_STDMETHODIMP DrawGlyphRun(
         void* clientDrawingContext,
         FLOAT baselineOriginX,
         FLOAT baselineOriginY,
@@ -557,7 +581,7 @@
         return S_OK;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
+    SK_STDMETHODIMP DrawUnderline(
         void* clientDrawingContext,
         FLOAT baselineOriginX,
         FLOAT baselineOriginY,
@@ -565,7 +589,7 @@
         IUnknown* clientDrawingEffect) override
     { return E_NOTIMPL; }
 
-    virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
+    SK_STDMETHODIMP DrawStrikethrough(
         void* clientDrawingContext,
         FLOAT baselineOriginX,
         FLOAT baselineOriginY,
@@ -573,7 +597,7 @@
         IUnknown* clientDrawingEffect) override
     { return E_NOTIMPL; }
 
-    virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
+    SK_STDMETHODIMP DrawInlineObject(
         void* clientDrawingContext,
         FLOAT originX,
         FLOAT originY,
@@ -584,7 +608,7 @@
     { return E_NOTIMPL; }
 
     // IDWritePixelSnapping methods
-    virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
+    SK_STDMETHODIMP IsPixelSnappingDisabled(
         void* clientDrawingContext,
         BOOL* isDisabled) override
     {
@@ -592,7 +616,7 @@
         return S_OK;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
+    SK_STDMETHODIMP GetCurrentTransform(
         void* clientDrawingContext,
         DWRITE_MATRIX* transform) override
     {
@@ -601,7 +625,7 @@
         return S_OK;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
+    SK_STDMETHODIMP GetPixelsPerDip(
         void* clientDrawingContext,
         FLOAT* pixelsPerDip) override
     {
@@ -609,35 +633,11 @@
         return S_OK;
     }
 
-    // IUnknown methods
-    ULONG STDMETHODCALLTYPE AddRef() override {
-        return InterlockedIncrement(&fRefCount);
-    }
-
-    ULONG STDMETHODCALLTYPE Release() override {
-        ULONG newCount = InterlockedDecrement(&fRefCount);
-        if (0 == newCount) {
-            delete this;
-        }
-        return newCount;
-    }
-
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{
-        if (__uuidof(IUnknown) == riid ||
-            __uuidof(IDWritePixelSnapping) == riid ||
-            __uuidof(IDWriteTextRenderer) == riid)
-        {
-            *ppvObject = this;
-            this->AddRef();
-            return S_OK;
-        }
-        *ppvObject = nullptr;
-        return E_FAIL;
-    }
-
     sk_sp<SkTypeface> ConsumeFallbackTypeface() { return std::move(fResolvedTypeface); }
 
-protected:
+private:
+    virtual ~FontFallbackRenderer() { }
+
     ULONG fRefCount;
     sk_sp<const SkFontMgr_DirectWrite> fOuter;
     UINT32 fCharacter;
@@ -655,10 +655,33 @@
         , fNumberSubstitution(numberSubstitution)
     { }
 
-    virtual ~FontFallbackSource() { }
+    // IUnknown methods
+    SK_STDMETHODIMP QueryInterface(IID const& riid, void** ppvObject) override {
+        if (__uuidof(IUnknown) == riid ||
+            __uuidof(IDWriteTextAnalysisSource) == riid)
+        {
+            *ppvObject = this;
+            this->AddRef();
+            return S_OK;
+        }
+        *ppvObject = nullptr;
+        return E_FAIL;
+    }
+
+    SK_STDMETHODIMP_(ULONG) AddRef() override {
+        return InterlockedIncrement(&fRefCount);
+    }
+
+    SK_STDMETHODIMP_(ULONG) Release() override {
+        ULONG newCount = InterlockedDecrement(&fRefCount);
+        if (0 == newCount) {
+            delete this;
+        }
+        return newCount;
+    }
 
     // IDWriteTextAnalysisSource methods
-    virtual HRESULT STDMETHODCALLTYPE GetTextAtPosition(
+    SK_STDMETHODIMP GetTextAtPosition(
         UINT32 textPosition,
         WCHAR const** textString,
         UINT32* textLength) override
@@ -673,7 +696,7 @@
         return S_OK;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE GetTextBeforePosition(
+    SK_STDMETHODIMP GetTextBeforePosition(
         UINT32 textPosition,
         WCHAR const** textString,
         UINT32* textLength) override
@@ -688,12 +711,12 @@
         return S_OK;
     }
 
-    virtual DWRITE_READING_DIRECTION STDMETHODCALLTYPE GetParagraphReadingDirection() override {
+    SK_STDMETHODIMP_(DWRITE_READING_DIRECTION) GetParagraphReadingDirection() override {
         // TODO: this is also interesting.
         return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE GetLocaleName(
+    SK_STDMETHODIMP GetLocaleName(
         UINT32 textPosition,
         UINT32* textLength,
         WCHAR const** localeName) override
@@ -702,7 +725,7 @@
         return S_OK;
     }
 
-    virtual HRESULT STDMETHODCALLTYPE GetNumberSubstitution(
+    SK_STDMETHODIMP GetNumberSubstitution(
         UINT32 textPosition,
         UINT32* textLength,
         IDWriteNumberSubstitution** numberSubstitution) override
@@ -711,32 +734,9 @@
         return S_OK;
     }
 
-    // IUnknown methods
-    ULONG STDMETHODCALLTYPE AddRef() override {
-        return InterlockedIncrement(&fRefCount);
-    }
+private:
+    virtual ~FontFallbackSource() { }
 
-    ULONG STDMETHODCALLTYPE Release() override {
-        ULONG newCount = InterlockedDecrement(&fRefCount);
-        if (0 == newCount) {
-            delete this;
-        }
-        return newCount;
-    }
-
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject) override{
-        if (__uuidof(IUnknown) == riid ||
-            __uuidof(IDWriteTextAnalysisSource) == riid)
-        {
-            *ppvObject = this;
-            this->AddRef();
-            return S_OK;
-        }
-        *ppvObject = nullptr;
-        return E_FAIL;
-    }
-
-protected:
     ULONG fRefCount;
     const WCHAR* fString;
     UINT32 fLength;
diff --git a/src/ports/SkRemotableFontMgr_win_dw.cpp b/src/ports/SkRemotableFontMgr_win_dw.cpp
index 85f8b02..fc9c6d8 100644
--- a/src/ports/SkRemotableFontMgr_win_dw.cpp
+++ b/src/ports/SkRemotableFontMgr_win_dw.cpp
@@ -20,6 +20,7 @@
 #include "src/utils/win/SkDWrite.h"
 #include "src/utils/win/SkDWriteFontFileStream.h"
 #include "src/utils/win/SkHRESULT.h"
+#include "src/utils/win/SkObjBase.h"
 #include "src/utils/win/SkTScopedComPtr.h"
 
 #include <dwrite.h>
@@ -236,7 +237,7 @@
         virtual ~FontFallbackRenderer() { }
 
         // IDWriteTextRenderer methods
-        virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
+        SK_STDMETHODIMP DrawGlyphRun(
             void* clientDrawingContext,
             FLOAT baselineOriginX,
             FLOAT baselineOriginY,
@@ -262,7 +263,7 @@
             return S_OK;
         }
 
-        virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
+        SK_STDMETHODIMP DrawUnderline(
             void* clientDrawingContext,
             FLOAT baselineOriginX,
             FLOAT baselineOriginY,
@@ -270,7 +271,7 @@
             IUnknown* clientDrawingEffect) override
         { return E_NOTIMPL; }
 
-        virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
+        SK_STDMETHODIMP DrawStrikethrough(
             void* clientDrawingContext,
             FLOAT baselineOriginX,
             FLOAT baselineOriginY,
@@ -278,7 +279,7 @@
             IUnknown* clientDrawingEffect) override
         { return E_NOTIMPL; }
 
-        virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
+        SK_STDMETHODIMP DrawInlineObject(
             void* clientDrawingContext,
             FLOAT originX,
             FLOAT originY,
@@ -289,7 +290,7 @@
         { return E_NOTIMPL; }
 
         // IDWritePixelSnapping methods
-        virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
+        SK_STDMETHODIMP IsPixelSnappingDisabled(
             void* clientDrawingContext,
             BOOL* isDisabled) override
         {
@@ -297,7 +298,7 @@
             return S_OK;
         }
 
-        virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
+        SK_STDMETHODIMP GetCurrentTransform(
             void* clientDrawingContext,
             DWRITE_MATRIX* transform) override
         {
@@ -306,7 +307,7 @@
             return S_OK;
         }
 
-        virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
+        SK_STDMETHODIMP GetPixelsPerDip(
             void* clientDrawingContext,
             FLOAT* pixelsPerDip) override
         {
@@ -315,11 +316,11 @@
         }
 
         // IUnknown methods
-        ULONG STDMETHODCALLTYPE AddRef() override {
+        SK_STDMETHODIMP_(ULONG) AddRef() override {
             return InterlockedIncrement(&fRefCount);
         }
 
-        ULONG STDMETHODCALLTYPE Release() override {
+        SK_STDMETHODIMP_(ULONG) Release() override {
             ULONG newCount = InterlockedDecrement(&fRefCount);
             if (0 == newCount) {
                 delete this;
@@ -327,7 +328,7 @@
             return newCount;
         }
 
-        virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+        SK_STDMETHODIMP QueryInterface(
             IID const& riid, void** ppvObject) override
         {
             if (__uuidof(IUnknown) == riid ||
diff --git a/src/utils/win/SkDWriteFontFileStream.cpp b/src/utils/win/SkDWriteFontFileStream.cpp
index 8c102cf..a3448d3 100644
--- a/src/utils/win/SkDWriteFontFileStream.cpp
+++ b/src/utils/win/SkDWriteFontFileStream.cpp
@@ -149,7 +149,7 @@
     : fRefCount(1), fStream(stream) {
 }
 
-HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
+SK_STDMETHODIMP SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) {
     if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) {
         *ppvObject = this;
         AddRef();
@@ -160,11 +160,11 @@
     }
 }
 
-ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::AddRef() {
+SK_STDMETHODIMP_(ULONG) SkDWriteFontFileStreamWrapper::AddRef() {
     return InterlockedIncrement(&fRefCount);
 }
 
-ULONG STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::Release() {
+SK_STDMETHODIMP_(ULONG) SkDWriteFontFileStreamWrapper::Release() {
     ULONG newCount = InterlockedDecrement(&fRefCount);
     if (0 == newCount) {
         delete this;
@@ -172,7 +172,7 @@
     return newCount;
 }
 
-HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment(
+SK_STDMETHODIMP SkDWriteFontFileStreamWrapper::ReadFileFragment(
     void const** fragmentStart,
     UINT64 fileOffset,
     UINT64 fragmentSize,
@@ -217,16 +217,16 @@
     return S_OK;
 }
 
-void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
+SK_STDMETHODIMP_(void) SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) {
     sk_free(fragmentContext);
 }
 
-HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
+SK_STDMETHODIMP SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) {
     *fileSize = fStream->getLength();
     return S_OK;
 }
 
-HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
+SK_STDMETHODIMP SkDWriteFontFileStreamWrapper::GetLastWriteTime(UINT64* lastWriteTime) {
     // The concept of last write time does not apply to this loader.
     *lastWriteTime = 0;
     return E_NOTIMPL;
diff --git a/src/utils/win/SkDWriteFontFileStream.h b/src/utils/win/SkDWriteFontFileStream.h
index ddafe79..d39b021 100644
--- a/src/utils/win/SkDWriteFontFileStream.h
+++ b/src/utils/win/SkDWriteFontFileStream.h
@@ -12,6 +12,7 @@
 
 #include "include/core/SkStream.h"
 #include "include/private/SkMutex.h"
+#include "src/utils/win/SkObjBase.h"
 #include "src/utils/win/SkTScopedComPtr.h"
 
 #include <dwrite.h>
@@ -58,20 +59,20 @@
 class SkDWriteFontFileStreamWrapper : public IDWriteFontFileStream {
 public:
     // IUnknown methods
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
-    virtual ULONG STDMETHODCALLTYPE AddRef();
-    virtual ULONG STDMETHODCALLTYPE Release();
+    SK_STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override;
+    SK_STDMETHODIMP_(ULONG) AddRef() override;
+    SK_STDMETHODIMP_(ULONG) Release() override;
 
     // IDWriteFontFileStream methods
-    virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(
+    SK_STDMETHODIMP ReadFileFragment(
         void const** fragmentStart,
         UINT64 fileOffset,
         UINT64 fragmentSize,
-        void** fragmentContext);
+        void** fragmentContext) override;
 
-    virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
-    virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* fileSize);
-    virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* lastWriteTime);
+    SK_STDMETHODIMP_(void) ReleaseFileFragment(void* fragmentContext) override;
+    SK_STDMETHODIMP GetFileSize(UINT64* fileSize) override;
+    SK_STDMETHODIMP GetLastWriteTime(UINT64* lastWriteTime) override;
 
     static HRESULT Create(SkStreamAsset* stream,
                           SkDWriteFontFileStreamWrapper** streamFontFileStream);
diff --git a/src/utils/win/SkDWriteGeometrySink.cpp b/src/utils/win/SkDWriteGeometrySink.cpp
index d8a0975..65da6ae 100644
--- a/src/utils/win/SkDWriteGeometrySink.cpp
+++ b/src/utils/win/SkDWriteGeometrySink.cpp
@@ -11,6 +11,7 @@
 #include "include/core/SkPath.h"
 #include "src/utils/SkFloatUtils.h"
 #include "src/utils/win/SkDWriteGeometrySink.h"
+#include "src/utils/win/SkObjBase.h"
 
 #include <dwrite.h>
 #include <d2d1.h>
@@ -19,7 +20,7 @@
 
 SkDWriteGeometrySink::~SkDWriteGeometrySink() { }
 
-HRESULT STDMETHODCALLTYPE SkDWriteGeometrySink::QueryInterface(REFIID iid, void **object) {
+SK_STDMETHODIMP SkDWriteGeometrySink::QueryInterface(REFIID iid, void **object) {
     if (nullptr == object) {
         return E_INVALIDARG;
     }
@@ -33,11 +34,11 @@
     }
 }
 
-ULONG STDMETHODCALLTYPE SkDWriteGeometrySink::AddRef(void) {
+SK_STDMETHODIMP_(ULONG) SkDWriteGeometrySink::AddRef(void) {
     return static_cast<ULONG>(InterlockedIncrement(&fRefCount));
 }
 
-ULONG STDMETHODCALLTYPE SkDWriteGeometrySink::Release(void) {
+SK_STDMETHODIMP_(ULONG) SkDWriteGeometrySink::Release(void) {
     ULONG res = static_cast<ULONG>(InterlockedDecrement(&fRefCount));
     if (0 == res) {
         delete this;
@@ -45,7 +46,7 @@
     return res;
 }
 
-void STDMETHODCALLTYPE SkDWriteGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) {
+SK_STDMETHODIMP_(void) SkDWriteGeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) {
     switch (fillMode) {
     case D2D1_FILL_MODE_ALTERNATE:
         fPath->setFillType(SkPath::kEvenOdd_FillType);
@@ -59,20 +60,20 @@
     }
 }
 
-void STDMETHODCALLTYPE SkDWriteGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) {
+SK_STDMETHODIMP_(void) SkDWriteGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) {
     if (vertexFlags == D2D1_PATH_SEGMENT_NONE || vertexFlags == D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN) {
         SkDEBUGFAIL("Invalid D2D1_PATH_SEGMENT value.");
     }
 }
 
-void STDMETHODCALLTYPE SkDWriteGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) {
+SK_STDMETHODIMP_(void) SkDWriteGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) {
     fPath->moveTo(startPoint.x, startPoint.y);
     if (figureBegin == D2D1_FIGURE_BEGIN_HOLLOW) {
         SkDEBUGFAIL("Invalid D2D1_FIGURE_BEGIN value.");
     }
 }
 
-void STDMETHODCALLTYPE SkDWriteGeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) {
+SK_STDMETHODIMP_(void) SkDWriteGeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) {
     for (const D2D1_POINT_2F *end = &points[pointsCount]; points < end; ++points) {
         fPath->lineTo(points->x, points->y);
     }
@@ -110,7 +111,7 @@
     return true;
 }
 
-void STDMETHODCALLTYPE SkDWriteGeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) {
+SK_STDMETHODIMP_(void) SkDWriteGeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) {
     SkPoint lastPt;
     fPath->getLastPt(&lastPt);
     D2D1_POINT_2F prevPt = { SkScalarToFloat(lastPt.fX), SkScalarToFloat(lastPt.fY) };
@@ -133,11 +134,11 @@
     }
 }
 
-void STDMETHODCALLTYPE SkDWriteGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) {
+SK_STDMETHODIMP_(void) SkDWriteGeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) {
     fPath->close();
 }
 
-HRESULT SkDWriteGeometrySink::Close() {
+SK_STDMETHODIMP SkDWriteGeometrySink::Close() {
     return S_OK;
 }
 
diff --git a/src/utils/win/SkDWriteGeometrySink.h b/src/utils/win/SkDWriteGeometrySink.h
index 30b337f..019539b 100644
--- a/src/utils/win/SkDWriteGeometrySink.h
+++ b/src/utils/win/SkDWriteGeometrySink.h
@@ -9,6 +9,7 @@
 #define SkDWriteToPath_DEFINED
 
 #include "include/core/SkTypes.h"
+#include "src/utils/win/SkObjBase.h"
 
 class SkPath;
 
@@ -20,25 +21,22 @@
     LONG fRefCount;
     SkPath* fPath;
 
-    SkDWriteGeometrySink(const SkDWriteGeometrySink&);
-    SkDWriteGeometrySink& operator=(const SkDWriteGeometrySink&);
-
 protected:
     explicit SkDWriteGeometrySink(SkPath* path);
     virtual ~SkDWriteGeometrySink();
 
 public:
-    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object) override;
-    ULONG STDMETHODCALLTYPE AddRef(void) override;
-    ULONG STDMETHODCALLTYPE Release(void) override;
+    SK_STDMETHODIMP QueryInterface(REFIID iid, void **object) override;
+    SK_STDMETHODIMP_(ULONG) AddRef() override;
+    SK_STDMETHODIMP_(ULONG) Release() override;
 
-    void STDMETHODCALLTYPE SetFillMode(D2D1_FILL_MODE fillMode) override;
-    void STDMETHODCALLTYPE SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) override;
-    void STDMETHODCALLTYPE BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) override;
-    void STDMETHODCALLTYPE AddLines(const D2D1_POINT_2F *points, UINT pointsCount) override;
-    void STDMETHODCALLTYPE AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) override;
-    void STDMETHODCALLTYPE EndFigure(D2D1_FIGURE_END figureEnd) override;
-    HRESULT STDMETHODCALLTYPE Close() override;
+    SK_STDMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode) override;
+    SK_STDMETHODIMP_(void) SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags) override;
+    SK_STDMETHODIMP_(void) BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) override;
+    SK_STDMETHODIMP_(void) AddLines(const D2D1_POINT_2F *points, UINT pointsCount) override;
+    SK_STDMETHODIMP_(void) AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) override;
+    SK_STDMETHODIMP_(void) EndFigure(D2D1_FIGURE_END figureEnd) override;
+    SK_STDMETHODIMP Close() override;
 
     static HRESULT Create(SkPath* path, IDWriteGeometrySink** geometryToPath);
 };
diff --git a/src/utils/win/SkIStream.cpp b/src/utils/win/SkIStream.cpp
index 3e10209..e19128b 100644
--- a/src/utils/win/SkIStream.cpp
+++ b/src/utils/win/SkIStream.cpp
@@ -17,9 +17,7 @@
 SkBaseIStream::SkBaseIStream() : _refcount(1) { }
 SkBaseIStream::~SkBaseIStream() { }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
-                                                      , void ** ppvObject)
-{
+SK_STDMETHODIMP SkBaseIStream::QueryInterface(REFIID iid, void ** ppvObject) {
     if (nullptr == ppvObject) {
         return E_INVALIDARG;
     }
@@ -36,11 +34,11 @@
     }
 }
 
-ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
+SK_STDMETHODIMP_(ULONG) SkBaseIStream::AddRef() {
     return (ULONG)InterlockedIncrement(&_refcount);
 }
 
-ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) {
+SK_STDMETHODIMP_(ULONG) SkBaseIStream::Release() {
     ULONG res = (ULONG) InterlockedDecrement(&_refcount);
     if (0 == res) {
         delete this;
@@ -49,52 +47,40 @@
 }
 
 // ISequentialStream Interface
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
-                                            , ULONG cb
-                                            , ULONG* pcbRead)
+SK_STDMETHODIMP SkBaseIStream::Read(void* pv, ULONG cb, ULONG* pcbRead)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
-                                             , ULONG cb
-                                             , ULONG* pcbWritten)
+SK_STDMETHODIMP SkBaseIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten)
 { return E_NOTIMPL; }
 
 // IStream Interface
-HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
+SK_STDMETHODIMP SkBaseIStream::SetSize(ULARGE_INTEGER)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
-                                              , ULARGE_INTEGER
-                                              , ULARGE_INTEGER*
-                                              , ULARGE_INTEGER*)
+SK_STDMETHODIMP SkBaseIStream::CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
+SK_STDMETHODIMP SkBaseIStream::Commit(DWORD)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
+SK_STDMETHODIMP SkBaseIStream::Revert()
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
-                                                  , ULARGE_INTEGER
-                                                  , DWORD)
+SK_STDMETHODIMP SkBaseIStream::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
-                                                    , ULARGE_INTEGER
-                                                    , DWORD)
+SK_STDMETHODIMP SkBaseIStream::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
+SK_STDMETHODIMP SkBaseIStream::Clone(IStream**)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
-                                            , DWORD dwOrigin
-                                            , ULARGE_INTEGER* lpNewFilePointer)
+SK_STDMETHODIMP SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove,
+                                    DWORD dwOrigin,
+                                    ULARGE_INTEGER* lpNewFilePointer)
 { return E_NOTIMPL; }
 
-HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
-                                            , DWORD grfStatFlag)
+SK_STDMETHODIMP SkBaseIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag)
 { return E_NOTIMPL; }
 
 
@@ -116,10 +102,7 @@
     }
 }
 
-HRESULT SkIStream::CreateFromSkStream(SkStream* stream
-                                    , bool deleteOnRelease
-                                    , IStream ** ppStream)
-{
+HRESULT SkIStream::CreateFromSkStream(SkStream* stream, bool deleteOnRelease, IStream ** ppStream) {
     if (nullptr == stream) {
         return E_INVALIDARG;
     }
@@ -128,23 +111,20 @@
 }
 
 // ISequentialStream Interface
-HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
+SK_STDMETHODIMP SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
     *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
     this->fLocation.QuadPart += *pcbRead;
     return (*pcbRead == cb) ? S_OK : S_FALSE;
 }
 
-HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
-                                         , ULONG cb
-                                         , ULONG* pcbWritten)
-{
+SK_STDMETHODIMP SkIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
     return STG_E_CANTSAVE;
 }
 
 // IStream Interface
-HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
-                                        , DWORD dwOrigin
-                                        , ULARGE_INTEGER* lpNewFilePointer)
+SK_STDMETHODIMP SkIStream::Seek(LARGE_INTEGER liDistanceToMove,
+                                DWORD dwOrigin,
+                                ULARGE_INTEGER* lpNewFilePointer)
 {
     HRESULT hr = S_OK;
 
@@ -198,9 +178,7 @@
     return hr;
 }
 
-HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
-                                        , DWORD grfStatFlag)
-{
+SK_STDMETHODIMP SkIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
         return STG_E_INVALIDFLAG;
     }
@@ -229,18 +207,13 @@
     }
 }
 
-HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
-                                      , IStream ** ppStream)
-{
+HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream, IStream ** ppStream) {
     *ppStream = new SkWIStream(stream);
     return S_OK;
 }
 
 // ISequentialStream Interface
-HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
-                                          , ULONG cb
-                                          , ULONG* pcbWritten)
-{
+SK_STDMETHODIMP SkWIStream::Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
     HRESULT hr = S_OK;
     bool wrote = this->fSkWStream->write(pv, cb);
     if (wrote) {
@@ -253,14 +226,12 @@
 }
 
 // IStream Interface
-HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
+SK_STDMETHODIMP SkWIStream::Commit(DWORD) {
     this->fSkWStream->flush();
     return S_OK;
 }
 
-HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
-                                         , DWORD grfStatFlag)
-{
+SK_STDMETHODIMP SkWIStream::Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
         return STG_E_INVALIDFLAG;
     }
diff --git a/src/utils/win/SkIStream.h b/src/utils/win/SkIStream.h
index 186fb93..a8a3ee7 100644
--- a/src/utils/win/SkIStream.h
+++ b/src/utils/win/SkIStream.h
@@ -15,6 +15,7 @@
 #ifdef SK_BUILD_FOR_WIN
 
 #include "src/core/SkLeanWindows.h"
+#include "src/utils/win/SkObjBase.h"
 #include <ole2.h>
 
 class SkStream;
@@ -25,110 +26,76 @@
  * but returns E_NOTIMPL for all ISequentialStream and IStream methods.
  */
 class SkBaseIStream : public IStream {
-private:
-    LONG _refcount;
+public:
+    // IUnknown methods
+    SK_STDMETHODIMP QueryInterface(REFIID iid, void ** ppvObject) override;
+    SK_STDMETHODIMP_(ULONG) AddRef() override;
+    SK_STDMETHODIMP_(ULONG) Release() override;
+
+    // ISequentialStream methods
+    SK_STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead) override;
+    SK_STDMETHODIMP Write(void const* pv, ULONG cb, ULONG* pcbWritten) override;
+
+    // IStream methods
+    SK_STDMETHODIMP SetSize(ULARGE_INTEGER) override;
+    SK_STDMETHODIMP CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) override;
+    SK_STDMETHODIMP Commit(DWORD) override;
+    SK_STDMETHODIMP Revert() override;
+    SK_STDMETHODIMP LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) override;
+    SK_STDMETHODIMP UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) override;
+    SK_STDMETHODIMP Clone(IStream**) override;
+    SK_STDMETHODIMP Seek(LARGE_INTEGER liDistanceToMove,
+                         DWORD dwOrigin,
+                         ULARGE_INTEGER* lpNewFilePointer) override;
+    SK_STDMETHODIMP Stat(STATSTG* pStatstg, DWORD grfStatFlag) override;
 
 protected:
     explicit SkBaseIStream();
     virtual ~SkBaseIStream();
 
-public:
-    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid
-                                                   , void ** ppvObject);
-    virtual ULONG STDMETHODCALLTYPE AddRef(void);
-    virtual ULONG STDMETHODCALLTYPE Release(void);
-
-    // ISequentialStream Interface
-public:
-    virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead);
-
-    virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
-                                          , ULONG cb
-                                          , ULONG* pcbWritten);
-
-    // IStream Interface
-public:
-    virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER);
-
-    virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*
-                                           , ULARGE_INTEGER
-                                           , ULARGE_INTEGER*
-                                           , ULARGE_INTEGER*);
-
-    virtual HRESULT STDMETHODCALLTYPE Commit(DWORD);
-
-    virtual HRESULT STDMETHODCALLTYPE Revert(void);
-
-    virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER
-                                               , ULARGE_INTEGER
-                                               , DWORD);
-
-    virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER
-                                                 , ULARGE_INTEGER
-                                                 , DWORD);
-
-    virtual HRESULT STDMETHODCALLTYPE Clone(IStream **);
-
-    virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove
-                                         , DWORD dwOrigin
-                                         , ULARGE_INTEGER* lpNewFilePointer);
-
-    virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
-                                         , DWORD grfStatFlag);
+private:
+    LONG _refcount;
 };
 
 /**
  * A minimal read-only IStream implementation which wraps an SkStream.
  */
 class SkIStream : public SkBaseIStream {
+public:
+    HRESULT static CreateFromSkStream(SkStream* stream, bool fDeleteOnRelease, IStream** ppStream);
+
+    SK_STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead) override;
+    SK_STDMETHODIMP Write(void const* pv, ULONG cb, ULONG* pcbWritten) override;
+    SK_STDMETHODIMP Seek(LARGE_INTEGER liDistanceToMove,
+                         DWORD dwOrigin,
+                         ULARGE_INTEGER* lpNewFilePointer) override;
+    SK_STDMETHODIMP Stat(STATSTG* pStatstg, DWORD grfStatFlag) override;
+
 private:
     SkStream *fSkStream;
     const bool fDeleteOnRelease;
     ULARGE_INTEGER fLocation;
 
     SkIStream(SkStream* stream, bool fDeleteOnRelease);
-    virtual ~SkIStream();
-
-public:
-    HRESULT static CreateFromSkStream(SkStream* stream
-                                    , bool fDeleteOnRelease
-                                    , IStream ** ppStream);
-
-    virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead);
-
-    virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
-                                          , ULONG cb
-                                          , ULONG* pcbWritten);
-
-    virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove
-                                         , DWORD dwOrigin
-                                         , ULARGE_INTEGER* lpNewFilePointer);
-
-    virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
-                                         , DWORD grfStatFlag);
+    ~SkIStream() override;
 };
 
 /**
  * A minimal write-only IStream implementation which wraps an SkWIStream.
  */
 class SkWIStream : public SkBaseIStream {
+public:
+    HRESULT static CreateFromSkWStream(SkWStream* stream, IStream ** ppStream);
+
+    SK_STDMETHODIMP Write(void const* pv, ULONG cb, ULONG* pcbWritten) override;
+    SK_STDMETHODIMP Commit(DWORD) override;
+    SK_STDMETHODIMP Stat(STATSTG* pStatstg, DWORD grfStatFlag) override;
+
 private:
     SkWStream *fSkWStream;
 
     SkWIStream(SkWStream* stream);
-    virtual ~SkWIStream();
-
-public:
-    HRESULT static CreateFromSkWStream(SkWStream* stream, IStream ** ppStream);
-
-    virtual HRESULT STDMETHODCALLTYPE Write(void const* pv
-                                          , ULONG cb
-                                          , ULONG* pcbWritten);
-
-    virtual HRESULT STDMETHODCALLTYPE Commit(DWORD);
-
-    virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg
-                                         , DWORD grfStatFlag);
+    ~SkWIStream() override;
 };
 
 #endif  // SK_BUILD_FOR_WIN
diff --git a/src/utils/win/SkObjBase.h b/src/utils/win/SkObjBase.h
new file mode 100644
index 0000000..a85cc90
--- /dev/null
+++ b/src/utils/win/SkObjBase.h
@@ -0,0 +1,25 @@
+/*
+* Copyright 2019 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef SkObjBase_DEFINED
+#define SkObjBase_DEFINED
+
+#include "src/core/SkLeanWindows.h"
+#include <objbase.h>
+
+// STDMETHOD uses COM_DECLSPEC_NOTHROW, but STDMETHODIMP does not. This leads to attribute mismatch
+// between interfaces and implementations which produces warnings. In theory a COM component should
+// never throw a c++ exception, but COM_DECLSPEC_NOTHROW allows tweaking that (as it may be useful
+// for internal only implementations within a single project). The behavior of the attribute nothrow
+// and the keyword noexcept are slightly different, so use COM_DECLSPEC_NOTHROW instead of noexcept.
+// Older interfaces like IUnknown and IStream do not currently specify COM_DECLSPEC_NOTHROW, but it
+// is not harmful to mark the implementation more exception strict than the interface.
+
+#define SK_STDMETHODIMP COM_DECLSPEC_NOTHROW STDMETHODIMP
+#define SK_STDMETHODIMP_(type) COM_DECLSPEC_NOTHROW STDMETHODIMP_(type)
+
+#endif
diff --git a/src/utils/win/SkTScopedComPtr.h b/src/utils/win/SkTScopedComPtr.h
index 2399d30..d8cba3c 100644
--- a/src/utils/win/SkTScopedComPtr.h
+++ b/src/utils/win/SkTScopedComPtr.h
@@ -9,17 +9,10 @@
 #define SkTScopedComPtr_DEFINED
 
 #include "src/core/SkLeanWindows.h"
+#include "src/utils/win/SkObjBase.h"
 
 #ifdef SK_BUILD_FOR_WIN
 
-template<typename T>
-class SkBlockComRef : public T {
-private:
-    virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
-    virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
-    virtual ~SkBlockComRef() {}
-};
-
 template<typename T> T* SkRefComPtr(T* ptr) {
     ptr->AddRef();
     return ptr;
@@ -57,7 +50,7 @@
 
     explicit operator bool() const { return fPtr != nullptr; }
 
-    SkBlockComRef<T> *operator->() const { return static_cast<SkBlockComRef<T>*>(fPtr); }
+    T *operator->() const { return fPtr; }
 
     /**
      * Returns the address of the underlying pointer.