topical media & game development

talk show tell print

hush-src-multi-BaseClasses-dllsetup.cpp / cpp



  //------------------------------------------------------------------------------
  // File: DllSetup.cpp
  //
  // Desc: DirectShow base classes.
  //
  // Copyright (c) Microsoft Corporation.  All rights reserved.
  //------------------------------------------------------------------------------
  
  include <streams.h>
  
  //---------------------------------------------------------------------------
  // defines
  
  define MAX_KEY_LEN  260
  
  //---------------------------------------------------------------------------
  // externally defined functions/variable
  
  extern int g_cTemplates;
  extern CFactoryTemplate g_Templates[];
  
  //---------------------------------------------------------------------------
  //
  // EliminateSubKey
  //
  // Try to enumerate all keys under this one.
  // if we find anything, delete it completely.
  // Otherwise just delete it.
  //
  // note - this was pinched/duplicated from
  // Filgraph\Mapper.cpp - so should it be in
  // a lib somewhere?
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  EliminateSubKey( HKEY hkey, LPTSTR strSubKey )
  {
    HKEY hk;
    if (0 == lstrlen(strSubKey) ) {
        // defensive approach
        return E_FAIL;
    }
  
    LONG lreturn = RegOpenKeyEx( hkey
                               , strSubKey
                               , 0
                               , MAXIMUM_ALLOWED
                               , &hk );
  
    ASSERT(    lreturn == ERROR_SUCCESS
            || lreturn == ERROR_FILE_NOT_FOUND
            || lreturn == ERROR_INVALID_HANDLE );
  
    if( ERROR_SUCCESS == lreturn )
    {
      // Keep on enumerating the first (zero-th)
      // key and deleting that
  
      for( ; ; )
      {
        TCHAR Buffer[MAX_KEY_LEN];
        DWORD dw = MAX_KEY_LEN;
        FILETIME ft;
  
        lreturn = RegEnumKeyEx( hk
                              , 0
                              , Buffer
                              , &dw
                              , NULL
                              , NULL
                              , NULL
                              , &ft);
  
        ASSERT(    lreturn == ERROR_SUCCESS
                || lreturn == ERROR_NO_MORE_ITEMS );
  
        if( ERROR_SUCCESS == lreturn )
        {
          EliminateSubKey(hk, Buffer);
        }
        else
        {
          break;
        }
      }
  
      RegCloseKey(hk);
      RegDeleteKey(hkey, strSubKey);
    }
  
    return NOERROR;
  }
  
  //---------------------------------------------------------------------------
  //
  // AMovieSetupRegisterServer()
  //
  // registers specfied file "szFileName" as server for
  // CLSID "clsServer".  A description is also required.
  // The ThreadingModel and ServerType are optional, as
  // they default to InprocServer32 (i.e. dll) and Both.
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  AMovieSetupRegisterServer( CLSID   clsServer
                           , LPCWSTR szDescription
                           , LPCWSTR szFileName
                           , LPCWSTR szThreadingModel = L"Both"
                           , LPCWSTR szServerType     = L"InprocServer32" )
  {
    // temp buffer
    //
    TCHAR achTemp[MAX_PATH];
  
    // convert CLSID uuid to string and write
    // out subkey as string - CLSID{}
    //
    OLECHAR szCLSID[CHARS_IN_GUID];
    HRESULT hr = StringFromGUID2( clsServer
                                , szCLSID
                                , CHARS_IN_GUID );
    ASSERT( SUCCEEDED(hr) );
  
    // create key
    //
    HKEY hkey;
    wsprintf( achTemp, TEXT("CLSID\%ls"), szCLSID );
    LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT
                               , (LPCTSTR)achTemp
                               , &hkey              );
    if( ERROR_SUCCESS != lreturn )
    {
      return AmHresultFromWin32(lreturn);
    }
  
    // set description string
    //
  
    wsprintf( achTemp, TEXT("\%ls"), szDescription );
    lreturn = RegSetValue( hkey
                         , (LPCTSTR)NULL
                         , REG_SZ
                         , achTemp
                         , sizeof(achTemp) );
    if( ERROR_SUCCESS != lreturn )
    {
      RegCloseKey( hkey );
      return AmHresultFromWin32(lreturn);
    }
  
    // create CLSID\{"CLSID"}\\"ServerType" key,
    // using key to CLSID\{"CLSID"} passed back by
    // last call to RegCreateKey().
    //
    HKEY hsubkey;
  
    wsprintf( achTemp, TEXT("\%ls"), szServerType );
    lreturn = RegCreateKey( hkey
                          , achTemp
                          , &hsubkey     );
    if( ERROR_SUCCESS != lreturn )
    {
      RegCloseKey( hkey );
      return AmHresultFromWin32(lreturn);
    }
  
    // set Server string
    //
    wsprintf( achTemp, TEXT("\%ls"), szFileName );
    lreturn = RegSetValue( hsubkey
                         , (LPCTSTR)NULL
                         , REG_SZ
                         , (LPCTSTR)achTemp
                         , sizeof(TCHAR) * (lstrlen(achTemp)+1) );
    if( ERROR_SUCCESS != lreturn )
    {
      RegCloseKey( hkey );
      RegCloseKey( hsubkey );
      return AmHresultFromWin32(lreturn);
    }
  
    wsprintf( achTemp, TEXT("\%ls"), szThreadingModel );
    lreturn = RegSetValueEx( hsubkey
                           , TEXT("ThreadingModel")
                           , 0L
                           , REG_SZ
                           , (CONST BYTE *)achTemp
                           , sizeof(TCHAR) * (lstrlen(achTemp)+1) );
  
    // close hkeys
    //
    RegCloseKey( hkey );
    RegCloseKey( hsubkey );
  
    // and return
    //
    return HRESULT_FROM_WIN32(lreturn);
  
  }
  
  //---------------------------------------------------------------------------
  //
  // AMovieSetupUnregisterServer()
  //
  // default ActiveMovie dll setup function
  // - to use must be called from an exported
  //   function named DllRegisterServer()
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  AMovieSetupUnregisterServer( CLSID clsServer )
  {
    // convert CLSID uuid to string and write
    // out subkey CLSID{}
    //
    OLECHAR szCLSID[CHARS_IN_GUID];
    HRESULT hr = StringFromGUID2( clsServer
                                , szCLSID
                                , CHARS_IN_GUID );
    ASSERT( SUCCEEDED(hr) );
  
    TCHAR achBuffer[MAX_KEY_LEN];
    wsprintf( achBuffer, TEXT("CLSID\%ls"), szCLSID );
  
    // delete subkey
    //
  
    hr = EliminateSubKey( HKEY_CLASSES_ROOT, achBuffer );
    ASSERT( SUCCEEDED(hr) );
  
    // return
    //
    return NOERROR;
  }
  
  //---------------------------------------------------------------------------
  //
  // AMovieSetupRegisterFilter through IFilterMapper2
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
                            , IFilterMapper2 *                 pIFM2
                            , BOOL                             bRegister  )
  {
    DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));
  
    // check we've got data
    //
    if( NULL == psetupdata ) return S_FALSE;
  
    // unregister filter
    // (as pins are subkeys of filter's CLSID key
    // they do not need to be removed separately).
    //
    DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
    HRESULT hr = pIFM2->UnregisterFilter(
        0,                        // default category
        0,                        // default instance name
        *psetupdata->clsID );
  
    if( bRegister )
    {
      REGFILTER2 rf2;
      rf2.dwVersion = 1;
      rf2.dwMerit = psetupdata->dwMerit;
      rf2.cPins = psetupdata->nPins;
      rf2.rgPins = psetupdata->lpPin;
      
      // register filter
      //
      DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
      hr = pIFM2->RegisterFilter(*psetupdata->clsID
                               , psetupdata->strName
                               , 0 // moniker
                               , 0 // category
                               , NULL // instance
                               , &rf2);
    }
  
    // handle one acceptable "error" - that
    // of filter not being registered!
    // (couldn't find a suitable #define'd
    // name for the error!)
    //
    if( 0x80070002 == hr)
      return NOERROR;
    else
      return hr;
  }
  
  //---------------------------------------------------------------------------
  //
  // RegisterAllServers()
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  RegisterAllServers( LPCWSTR szFileName, BOOL bRegister )
  {
    HRESULT hr = NOERROR;
  
    for( int i = 0; i < g_cTemplates; i++ )
    {
      // get i'th template
      //
      const CFactoryTemplate *pT = &g_Templates[i];
  
      DbgLog((LOG_TRACE, 2, TEXT("- - register \%ls"),
             (LPCWSTR)pT->m_Name ));
  
      // register CLSID and InprocServer32
      //
      if( bRegister )
      {
        hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
                                      , (LPCWSTR)pT->m_Name
                                      , szFileName );
      }
      else
      {
        hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
      }
  
      // check final error for this pass
      // and break loop if we failed
      //
      if( FAILED(hr) )
        break;
    }
  
    return hr;
  }
  
  //---------------------------------------------------------------------------
  //
  // AMovieDllRegisterServer2()
  //
  // default ActiveMovie dll setup function
  // - to use must be called from an exported
  //   function named DllRegisterServer()
  //
  // this function is table driven using the
  // static members of the CFactoryTemplate
  // class defined in the dll.
  //
  // it registers the Dll as the InprocServer32
  // and then calls the IAMovieSetup.Register
  // method.
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  AMovieDllRegisterServer2( BOOL bRegister )
  {
    HRESULT hr = NOERROR;
  
    DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()")));
  
    // get file name (where g_hInst is the
    // instance handle of the filter dll)
    //
    WCHAR achFileName[MAX_PATH];
  
    // WIN95 doesn't support GetModuleFileNameW
    //
    {
      char achTemp[MAX_PATH];
  
      DbgLog((LOG_TRACE, 2, TEXT("- get module file name")));
  
      // g_hInst handle is set in our dll entry point. Make sure
      // DllEntryPoint in dllentry.cpp is called
      ASSERT(g_hInst != 0);
  
      if( 0 == GetModuleFileNameA( g_hInst
                                , achTemp
                                , sizeof(achTemp) ) )
      {
        // we've failed!
        DWORD dwerr = GetLastError();
        return AmHresultFromWin32(dwerr);
      }
  
      MultiByteToWideChar( CP_ACP
                         , 0L
                         , achTemp
                         , lstrlenA(achTemp) + 1
                         , achFileName
                         , NUMELMS(achFileName) );
    }
  
    //
    // first registering, register all OLE servers
    //
    if( bRegister )
    {
      DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
      hr = RegisterAllServers( achFileName, TRUE );
    }
  
    //
    // next, register/unregister all filters
    //
  
    if( SUCCEEDED(hr) )
    {
      // init is ref counted so call just in case
      // we're being called cold.
      //
      DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize")));
      hr = CoInitialize( (LPVOID)NULL );
      ASSERT( SUCCEEDED(hr) );
  
      // get hold of IFilterMapper2
      //
      DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2")));
      IFilterMapper2 *pIFM2 = 0;
      IFilterMapper *pIFM = 0;
      hr = CoCreateInstance( CLSID_FilterMapper2
                           , NULL
                           , CLSCTX_INPROC_SERVER
                           , IID_IFilterMapper2
                           , (void **)&pIFM2       );
      if(FAILED(hr))
      {
          DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead")));
  
          hr = CoCreateInstance(
              CLSID_FilterMapper,
              NULL,
              CLSCTX_INPROC_SERVER,
              IID_IFilterMapper,
              (void **)&pIFM);
      }
      if( SUCCEEDED(hr) )
      {
        // scan through array of CFactoryTemplates
        // registering servers and filters.
        //
        DbgLog((LOG_TRACE, 2, TEXT("- register Filters")));
        for( int i = 0; i < g_cTemplates; i++ )
        {
          // get i'th template
          //
          const CFactoryTemplate *pT = &g_Templates[i];
  
          if( NULL != pT->m_pAMovieSetup_Filter )
          {
            DbgLog((LOG_TRACE, 2, TEXT("- - register \%ls"), (LPCWSTR)pT->m_Name ));
  
            if(pIFM2)
            {
                hr = AMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister );
            }
            else
            {
                hr = AMovieSetupRegisterFilter( pT->m_pAMovieSetup_Filter, pIFM, bRegister );
            }
          }
  
          // check final error for this pass
          // and break loop if we failed
          //
          if( FAILED(hr) )
            break;
        }
  
        // release interface
        //
        if(pIFM2)
            pIFM2->Release();
        else
            pIFM->Release();
  
      }
  
      // and clear up
      //
      CoFreeUnusedLibraries();
      CoUninitialize();
    }
  
    //
    // if unregistering, unregister all OLE servers
    //
    if( SUCCEEDED(hr) && !bRegister )
    {
      DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
      hr = RegisterAllServers( achFileName, FALSE );
    }
  
    DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr));
    return hr;
  }
  
  //---------------------------------------------------------------------------
  //
  // AMovieDllRegisterServer()
  //
  // default ActiveMovie dll setup function
  // - to use must be called from an exported
  //   function named DllRegisterServer()
  //
  // this function is table driven using the
  // static members of the CFactoryTemplate
  // class defined in the dll.
  //
  // it registers the Dll as the InprocServer32
  // and then calls the IAMovieSetup.Register
  // method.
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  AMovieDllRegisterServer( void )
  {
    HRESULT hr = NOERROR;
  
    // get file name (where g_hInst is the
    // instance handle of the filter dll)
    //
    WCHAR achFileName[MAX_PATH];
  
    {
      // WIN95 doesn't support GetModuleFileNameW
      //
      char achTemp[MAX_PATH];
  
      if( 0 == GetModuleFileNameA( g_hInst
                                , achTemp
                                , sizeof(achTemp) ) )
      {
        // we've failed!
        DWORD dwerr = GetLastError();
        return AmHresultFromWin32(dwerr);
      }
  
      MultiByteToWideChar( CP_ACP
                         , 0L
                         , achTemp
                         , lstrlenA(achTemp) + 1
                         , achFileName
                         , NUMELMS(achFileName) );
    }
  
    // scan through array of CFactoryTemplates
    // registering servers and filters.
    //
    for( int i = 0; i < g_cTemplates; i++ )
    {
      // get i'th template
      //
      const CFactoryTemplate *pT = &g_Templates[i];
  
      // register CLSID and InprocServer32
      //
      hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
                                    , (LPCWSTR)pT->m_Name
                                    , achFileName );
  
      // instantiate all servers and get hold of
      // IAMovieSetup, if implemented, and call
      // IAMovieSetup.Register() method
      //
      if( SUCCEEDED(hr) && (NULL != pT->m_lpfnNew) )
      {
        // instantiate object
        //
        PAMOVIESETUP psetup;
        hr = CoCreateInstance( *(pT->m_ClsID)
                             , 0
                             , CLSCTX_INPROC_SERVER
                             , IID_IAMovieSetup
                             , reinterpret_cast<void**>(&psetup) );
        if( SUCCEEDED(hr) )
        {
          hr = psetup->Unregister();
          if( SUCCEEDED(hr) )
            hr = psetup->Register();
          psetup->Release();
        }
        else
        {
          if(    (E_NOINTERFACE      == hr )
              || (VFW_E_NEED_OWNER == hr ) )
            hr = NOERROR;
        }
      }
  
      // check final error for this pass
      // and break loop if we failed
      //
      if( FAILED(hr) )
        break;
  
    } // end-for
  
    return hr;
  }
  
  //---------------------------------------------------------------------------
  //
  // AMovieDllUnregisterServer()
  //
  // default ActiveMovie dll uninstall function
  // - to use must be called from an exported
  //   function named DllRegisterServer()
  //
  // this function is table driven using the
  // static members of the CFactoryTemplate
  // class defined in the dll.
  //
  // it calls the IAMovieSetup.Unregister
  // method and then unregisters the Dll
  // as the InprocServer32
  //
  //---------------------------------------------------------------------------
  
  STDAPI
  AMovieDllUnregisterServer()
  {
    // initialize return code
    //
    HRESULT hr = NOERROR;
  
    // scan through CFactory template and unregister
    // all OLE servers and filters.
    //
    for( int i = g_cTemplates; i--; )
    {
      // get i'th template
      //
      const CFactoryTemplate *pT = &g_Templates[i];
  
      // check method exists
      //
      if( NULL != pT->m_lpfnNew )
      {
        // instantiate object
        //
        PAMOVIESETUP psetup;
        hr = CoCreateInstance( *(pT->m_ClsID)
                             , 0
                             , CLSCTX_INPROC_SERVER
                             , IID_IAMovieSetup
                             , reinterpret_cast<void**>(&psetup) );
        if( SUCCEEDED(hr) )
        {
          hr = psetup->Unregister();
          psetup->Release();
        }
        else
        {
          if(    (E_NOINTERFACE      == hr )
              || (VFW_E_NEED_OWNER == hr ) )
             hr = NOERROR;
        }
      }
  
      // unregister CLSID and InprocServer32
      //
      if( SUCCEEDED(hr) )
      {
        hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
      }
  
      // check final error for this pass
      // and break loop if we failed
      //
      if( FAILED(hr) )
        break;
    }
  
    return hr;
  }
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.