title: Using a custom DirectShow filter (DLL, registered)
body: <p>I've written a small transform filter (derived from TransInPlaceFilter baseclass), and managed to make it work properly in a Directshow graph, entirely coded in C++. I basically followed the 5 first steps described on <a href="http://msdn.microsoft.com/en-us/library/dd391015%28v=VS.85%29.aspx" rel="nofollow">MSDN</a>, and the last part of the 6th step (in order to use the filter directly within an application).</p>
  
  <p>For a lot of reasons (including being able to use the filter in GraphEdit), I need to export that filter in a DLL and register it.</p>
  
  <p>I've been trying to follow <a href="http://msdn.microsoft.com/en-us/library/dd389096%28v=VS.85%29.aspx" rel="nofollow">these steps</a> : setting up the "CreateInstance" method, the CFactoryTemplate class, filter/pins description (AMOVIESETUP_FILTER, AMOVIESETUP_PIN, AMOVIESETUP_MEDIA), Registering/Unregistering functions, and finally DLLmain/entrypoint.</p>
  
  <p>The code successfully compiles and provides a DLL, which seems to register without any problem using Regsvr32.</p>
  
  <p>But then I'm unable to use the filter :</p>
  
  <ul>
  <li>It appears in the list in GraphEdit, but fails when I try to insert it : 0x800401f9 ("Error in DLL"). </li>
  <li>When I try to create it in C++ (using <code>pCustomFilter.CoCreateInstance(CLSID_Custom)</code>, after defining the correct GUID), I get error 0x80040154 (REGDB_E_CLASSNOTREG)</li>
  </ul>
  
  <p>I'm quite confused here. Have I missed something in the DLL/registration code ? I'm posting most of the code I'm using, if it's of any use.</p>
  
  <p>Any help would be greatly appreciated.</p>
  
  <pre><code>static const WCHAR g_wszName[] = L"Custom Filter";
  
  AMOVIESETUP_MEDIATYPE sudMediaTypes[] = {
      { &amp;MEDIATYPE_Video, &amp;MEDIASUBTYPE_NULL },
      { &amp;MEDIATYPE_Audio, &amp;MEDIASUBTYPE_NULL },
  };
  
  AMOVIESETUP_PIN sudPins[2] = {
      {
          L"Input",            // Name
          FALSE,          // Is this pin rendered?
          FALSE,          // Is it an output pin?
          FALSE,          // Can the filter create zero instances?
          FALSE,          // Does the filter create multiple instances?
          &amp;GUID_NULL,     // Obsolete.
          NULL,           // Obsolete.
          2,              // Number of media types.
          sudMediaTypes   // Pointer to media types.
      },
      {
          L"Output",            // Name
          FALSE,          // Is this pin rendered?
          TRUE,           // Is it an output pin?
          FALSE,          // Can the filter create zero instances?
          FALSE,          // Does the filter create multiple instances?
          &amp;GUID_NULL,     // Obsolete.
          NULL,           // Obsolete.
          2,              // Number of media types.
          sudMediaTypes   // Pointer to media types.
      }
  };
  
  AMOVIESETUP_FILTER sudFilterReg = {
      &amp;CLSID_Custom,          // Filter CLSID.
      g_wszName,              // Filter name.
      MERIT_DO_NOT_USE,       // Merit.
      2,                      // Number of pin types.
      sudPins             // Pointer to pin information.
  };
  
  
  CFactoryTemplate g_Templates[] = 
  {
    { 
      g_wszName,
      &amp;CLSID_Custom,
      CCustomFilter::CreateInstance,
      NULL,
      &amp;sudFilterReg
    }
  };
  
  int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  
  STDAPI DllRegisterServer()
  {
      return AMovieDllRegisterServer2( TRUE );
  }
  STDAPI DllUnregisterServer()
  {
      return AMovieDllRegisterServer2( FALSE );
  }
  
  
  extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  
  BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
  {
      return DllEntryPoint(reinterpret_cast&lt;HINSTANCE&gt;(hDllHandle), dwReason, lpReserved);
  }
  
  // ---
  // Meanwhile, in my filter class...
  // ---
  CUnknown * WINAPI CCustomFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
  {
      CCustomFilter *pFilter = new CCustomFilter();
      if (pFilter== NULL) 
      {
          *pHr = E_OUTOFMEMORY;
      }
      return pFilter;
  }
  </code></pre>