Index: src/TortoiseOverlays/ShellExt.cpp
===================================================================
--- src/TortoiseOverlays/ShellExt.cpp	(revision 21716)
+++ src/TortoiseOverlays/ShellExt.cpp	(working copy)
@@ -11,12 +11,12 @@
 #include "ShellExt.h"
 
 // *********************** CShellExt *************************
+IMPLEMENT_UNKNOWN(CShellExt)
+
 CShellExt::CShellExt(FileState state)
 {
+    ADDIFACE(IShellIconOverlayIdentifier);
     m_State = state;
-
-    m_cRef = 0L;
-    InterlockedIncrement(&g_cRefThisDll);
 }
 
 CShellExt::~CShellExt()
@@ -38,43 +38,4 @@
         it->pDllCanUnloadNow = NULL;
     }
     m_dllpointers.clear();
-
-    InterlockedDecrement(&g_cRefThisDll);
 }
-
-STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv)
-{
-    if(ppv == 0)
-        return E_POINTER;
-    *ppv = NULL;
-
-    if (IsEqualIID(riid, IID_IUnknown))
-    {
-        *ppv = static_cast<IUnknown*>(this);
-    }
-    else if (IsEqualIID(riid, IID_IShellIconOverlayIdentifier))
-    {
-        *ppv = static_cast<IShellIconOverlayIdentifier*>(this);
-    }
-    else
-    {
-        return E_NOINTERFACE;
-    }
-
-    AddRef();
-    return S_OK;
-}
-
-STDMETHODIMP_(ULONG) CShellExt::AddRef()
-{
-    return ++m_cRef;
-}
-
-STDMETHODIMP_(ULONG) CShellExt::Release()
-{
-    if (--m_cRef)
-        return m_cRef;
-
-    delete this;
-    return 0L;
-}
Index: src/TortoiseOverlays/ShellExt.h
===================================================================
--- src/TortoiseOverlays/ShellExt.h	(revision 21716)
+++ src/TortoiseOverlays/ShellExt.h	(working copy)
@@ -5,6 +5,7 @@
 #include <vector>
 
 #include "resource.h"
+#include "SimpleUnknown.h"
 
 extern  volatile LONG       g_cRefThisDll;          // Reference count of this DLL.
 
@@ -44,11 +45,10 @@
  * The main class of our COM object / Shell Extension.
  * It contains all Interfaces we implement for the shell to use.
  */
-class CShellExt : public IShellIconOverlayIdentifier
+class CShellExt : public CSimpleUnknown, public IShellIconOverlayIdentifier
 {
 protected:
     FileState m_State;
-    ULONG   m_cRef;
 
     vector<DLLPointers>         m_dllpointers;
 
@@ -61,16 +61,8 @@
     CShellExt(FileState state);
     virtual ~CShellExt();
 
-    /** \name IUnknown
-     * IUnknown members
-     */
-    //@{
-    STDMETHODIMP         QueryInterface(REFIID, LPVOID FAR *);
-    STDMETHODIMP_(ULONG) AddRef();
-    STDMETHODIMP_(ULONG) Release();
-    //@}
+    DECLARE_UNKNOWN()
 
-
     /** \name IShellIconOverlayIdentifier
      * IShellIconOverlayIdentifier methods
      */
Index: src/TortoiseOverlays/ShellExtClassFactory.cpp
===================================================================
--- src/TortoiseOverlays/ShellExtClassFactory.cpp	(revision 21716)
+++ src/TortoiseOverlays/ShellExtClassFactory.cpp	(working copy)
@@ -4,57 +4,18 @@
 #include "ShellExt.h"
 #include "ShellExtClassFactory.h"
 
+IMPLEMENT_UNKNOWN(CShellExtClassFactory)
+
 CShellExtClassFactory::CShellExtClassFactory(FileState state)
 {
+    ADDIFACE(IClassFactory);
     m_StateToMake = state;
-
-    m_cRef = 0L;
-
-    InterlockedIncrement(&g_cRefThisDll);
 }
 
 CShellExtClassFactory::~CShellExtClassFactory()
 {
-    InterlockedDecrement(&g_cRefThisDll);
 }
 
-STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid,
-                                                   LPVOID FAR *ppv)
-{
-    if(ppv == 0)
-        return E_POINTER;
-
-    *ppv = NULL;
-
-    // Any interface on this object is the object pointer
-
-    if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
-    {
-        *ppv = static_cast<LPCLASSFACTORY>(this);
-
-        AddRef();
-
-        return S_OK;
-    }
-
-    return E_NOINTERFACE;
-}
-
-STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef()
-{
-    return ++m_cRef;
-}
-
-STDMETHODIMP_(ULONG) CShellExtClassFactory::Release()
-{
-    if (--m_cRef)
-        return m_cRef;
-
-    delete this;
-
-    return 0L;
-}
-
 STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
                                                    REFIID riid,
                                                    LPVOID *ppvObj)
Index: src/TortoiseOverlays/ShellExtClassFactory.h
===================================================================
--- src/TortoiseOverlays/ShellExtClassFactory.h	(revision 21716)
+++ src/TortoiseOverlays/ShellExtClassFactory.h	(working copy)
@@ -2,29 +2,23 @@
 // Copyright (C) 2007 - TortoiseSVN
 #pragma once
 
+#include "SimpleUnknown.h"
 
 /**
  * This class factory object creates the main handlers -
  * its constructor says which OLE class it has to make.
  */
-class CShellExtClassFactory : public IClassFactory
+class CShellExtClassFactory : public CSimpleUnknown, public IClassFactory
 {
 protected:
-    ULONG m_cRef;
     /// variable to contain class of object (i.e. not under source control, up to date)
     FileState       m_StateToMake;
 
-
 public:
     CShellExtClassFactory(FileState state);
     virtual ~CShellExtClassFactory();
 
-    //@{
-    /// IUnknown members
-    STDMETHODIMP         QueryInterface(REFIID, LPVOID FAR *);
-    STDMETHODIMP_(ULONG) AddRef();
-    STDMETHODIMP_(ULONG) Release();
-    //@}
+    DECLARE_UNKNOWN()
 
     //@{
     /// IClassFactory members
Index: src/TortoiseOverlays/SimpleUnknown.cpp
===================================================================
--- src/TortoiseOverlays/SimpleUnknown.cpp	(revision 0)
+++ src/TortoiseOverlays/SimpleUnknown.cpp	(revision 0)
@@ -0,0 +1,65 @@
+// Copyright (C) 2011 Fog Creek Software
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "stdafx.h"
+
+#include "SimpleUnknown.h"
+
+CSimpleUnknown::CSimpleUnknown()
+  : m_cRef(0)
+{
+    AddInterface(IID_IUnknown, this);
+}
+
+CSimpleUnknown::~CSimpleUnknown()
+{
+}
+
+void CSimpleUnknown::AddInterface(REFIID riid, LPUNKNOWN punk)
+{
+    Entry e(riid, punk);
+    m_entries.push_back(e);
+}
+
+STDMETHODIMP CSimpleUnknown::QueryInterface(REFIID riid, LPVOID FAR* ppv)
+{
+    if (ppv == NULL)
+        return E_POINTER;
+
+    for (vector<Entry>::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it)
+    {
+        if (it->iid == riid)
+        {
+            it->punk->AddRef();
+            *ppv = it->punk;
+            return S_OK;
+        }
+    }
+    *ppv = NULL;
+    return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CSimpleUnknown::AddRef()
+{
+    return ::InterlockedIncrement(&m_cRef);
+}
+
+STDMETHODIMP_(ULONG) CSimpleUnknown::Release()
+{
+    if (::InterlockedDecrement(&m_cRef))
+        return m_cRef;
+    delete this;
+    return 0L;
+}

Property changes on: src\TortoiseOverlays\SimpleUnknown.cpp
___________________________________________________________________
Added: svn:eol-style
   + native

Index: src/TortoiseOverlays/SimpleUnknown.h
===================================================================
--- src/TortoiseOverlays/SimpleUnknown.h	(revision 0)
+++ src/TortoiseOverlays/SimpleUnknown.h	(revision 0)
@@ -0,0 +1,81 @@
+// Copyright (C) 2011 Fog Creek Software
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#pragma once
+#include <vector>
+
+using namespace std;
+
+#define DECLARE_UNKNOWN() \
+    STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppv); \
+    STDMETHOD_(ULONG, AddRef)(); \
+    STDMETHOD_(ULONG, Release)(); \
+
+#define IMPLEMENT_UNKNOWN(classname) \
+    STDMETHODIMP classname::QueryInterface(REFIID riid, LPVOID FAR* ppv) \
+    { \
+        return CSimpleUnknown::QueryInterface(riid, ppv); \
+    } \
+    STDMETHODIMP_(ULONG) classname::AddRef() \
+    { \
+        return CSimpleUnknown::AddRef(); \
+    } \
+    STDMETHODIMP_(ULONG) classname::Release() \
+    { \
+        return CSimpleUnknown::Release(); \
+    }
+
+#define INLINE_UNKNOWN() \
+    STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppv) \
+    { \
+        return CSimpleUnknown::QueryInterface(riid, ppv); \
+    } \
+    STDMETHODIMP_(ULONG) AddRef() \
+    { \
+        return CSimpleUnknown::AddRef(); \
+    } \
+    STDMETHODIMP_(ULONG) Release() \
+    { \
+        return CSimpleUnknown::Release(); \
+    }
+
+#define ADDIFACE(iface) \
+    AddInterface(IID_##iface, (iface*)this)
+
+class CSimpleUnknown : public IUnknown
+{
+protected:
+    struct Entry
+    {
+        Entry(REFIID riid, LPUNKNOWN punk): iid(riid)
+            , punk(punk)
+        {
+        }
+
+        IID iid;
+        LPUNKNOWN punk;
+    };
+
+    vector<Entry> m_entries;
+    UINT m_cRef;
+    
+    void AddInterface(REFIID riid, IUnknown* punk);
+
+public:
+    CSimpleUnknown();
+    virtual ~CSimpleUnknown();
+
+    DECLARE_UNKNOWN()
+};

Property changes on: src\TortoiseOverlays\SimpleUnknown.h
___________________________________________________________________
Added: svn:eol-style
   + native

Index: src/TortoiseOverlays/TortoiseOverlays.vcxproj
===================================================================
--- src/TortoiseOverlays/TortoiseOverlays.vcxproj	(revision 21716)
+++ src/TortoiseOverlays/TortoiseOverlays.vcxproj	(working copy)
@@ -293,6 +293,7 @@
     <ClCompile Include="IconOverlay.cpp" />
     <ClCompile Include="ShellExt.cpp" />
     <ClCompile Include="ShellExtClassFactory.cpp" />
+    <ClCompile Include="SimpleUnknown.cpp" />
     <ClCompile Include="stdafx.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@@ -319,6 +320,7 @@
     <ClInclude Include="resource.h" />
     <ClInclude Include="ShellExt.h" />
     <ClInclude Include="ShellExtClassFactory.h" />
+    <ClInclude Include="SimpleUnknown.h" />
     <ClInclude Include="stdafx.h" />
   </ItemGroup>
   <ItemGroup>
Index: src/TortoiseOverlays/TortoiseOverlays.vcxproj.filters
===================================================================
--- src/TortoiseOverlays/TortoiseOverlays.vcxproj.filters	(revision 21716)
+++ src/TortoiseOverlays/TortoiseOverlays.vcxproj.filters	(working copy)
@@ -33,6 +33,9 @@
     <ClCompile Include="TortoiseOverlays.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="SimpleUnknown.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="ShellExt.def">
@@ -73,6 +76,9 @@
     <ClInclude Include="stdafx.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="SimpleUnknown.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="resource.rc">
