home *** CD-ROM | disk | FTP | other *** search
- /*
- * IFT_DLL.cpp
- * $Header: /bcsample/IFACEDLL/IFT_DLL.CPP 1 5/28/96 1:12p Dave $
- *
- * Description:
- * This file provides the main entry-points for OLE and the implementation
- * of the class factory for the Interface Test Object. The DLL is a
- * self-registering DLL.
- *
- * Notes:
- * To avoid a large memory and performance overhead for a simple OLE interface
- * testing object, MFC was not used. As a result, much of the design for the
- * DLL entry-points and class factory are based on the implementations from
- * Kraig Brockschmidt's book, "Inside OLE," the foremost resource on OLE
- * technology.
- *
- ***********************************************************************
- *
- * NuMega Technologies, Inc.
- * P.O. Box 7780
- * Nashua, NH 03060
- *
- * (c) Copyright 1994, 1995, 1996 NuMega Technologies, Inc.
- * ALL RIGHTS RESERVED.
- *
- ***********************************************************************
- *
- **********************************************************************/
-
- #include "IFT_OLE.h"
- #define INITGUIDS
-
- #include "IT_GUID.h"
- #include "IFT_DLL.h"
- #include "IUnknown.h"
- #include <tchar.h>
- #include <crtdbg.h>
-
- /*----------------------------------------------------------------------
- Constants - Strings
- ----------------------------------------------------------------------*/
- const TCHAR* gk_szModuleID = _T ( "IFACEDLL" ) ;
- const TCHAR* gk_szCLSID = _T ( "CLSID" ) ;
- const TCHAR* gk_szSlash = _T ( "\\" ) ;
- const TCHAR* gk_szProgID = _T ( "ProgID" ) ;
- const TCHAR* gk_szCurVer = _T ( "CurVer" ) ;
- const TCHAR* gk_szNotInsertable = _T ( "NotInsertable" ) ;
- const TCHAR* gk_szVersionIndependentProgID = _T ( "VersionIndependentProgID" ) ;
- const TCHAR* gk_szInprocServer32 = _T ( "InprocServer32" ) ;
- const TCHAR* gk_szIfaceTestObjectName = _T ( "InterfaceTest Object" ) ;
- const TCHAR* gk_szVerIfaceTestPRGID = _T ( "InterfaceTest1.0" ) ;
- const TCHAR* gk_szIfaceTestPRGID = _T ( "InterfaceTest" ) ;
-
- /*----------------------------------------------------------------------
- Constants - UINTs
- ----------------------------------------------------------------------*/
- const UINT gk_nMaxRegKeySize = 512 ;
- const UINT gk_nMakeRegExcept = 13 ;
- const UINT gk_nDelRegExcept = 113 ;
-
-
- // Count number of objects and number of locks.
- ULONG g_nObject = 0 ;
- ULONG g_nLock = 0 ;
-
- // The usual DLL entry point.
- BOOL WINAPI DllMain ( HINSTANCE ,
- ULONG ulReason ,
- LPVOID )
- {
- if ( DLL_PROCESS_ATTACH == ulReason )
- {
- // Turn of CRT library assertion dialogs.
- _CrtSetReportMode ( _CRT_ASSERT , _CRTDBG_MODE_DEBUG ) ;
- _CrtSetReportMode ( _CRT_ERROR , _CRTDBG_MODE_DEBUG ) ;
- _CrtSetReportMode ( _CRT_WARN , _CRTDBG_MODE_DEBUG ) ;
- }
-
- return ( TRUE ) ;
- }
-
- /*----------------------------------------------------------------------
- FUNCTION : DLLGetClassObject
- DISCUSSION :
- When an OLE object is exposed from an in-process server,
- CoGetClassObject calls this exported function to retrieve the class
- factory of the requested REFCLSID.
- PARAMETERS :
- rclsid - The class ID of the requested class. (More than one object
- can come from this DLL).
- riid - The ID of the interface that the user wants. This is
- usually IClassFactory.
- ppv - The variable that gets the interface.
- RETURN :
- NOERROR - Everything was OK and ppv holds a valid interface.
- E_FAIL - The CLSID requested is not part of this class.
- E_OUTOFMEMORY - There was not enough memory for the request.
- ----------------------------------------------------------------------*/
- // Note that the STDAPI resolves to "EXTERN_C HRESULT STDAPICALLTYPE"
- // Which sets up the extern "C" for us.
- STDAPI DllGetClassObject ( REFCLSID rclsid , REFIID riid , PPVOID ppv )
- {
- // The IClassFactory implementation class pointer.
- CIFaceTestClassFactory * pObj ;
- // The value we return.
- HRESULT hr = NOERROR ;
-
- // Set the interface return value to NULL just in case.
- *ppv = NULL ;
-
- // If the requested class is not the one we expose, then kick out.
- if ( CLSID_InterfaceTest != rclsid )
- {
- return ( E_FAIL ) ;
- }
-
- // Allocate the class.
- pObj = new CIFaceTestClassFactory ( ) ;
-
- // If we could not allocate it, return out of memory.
- if ( NULL == pObj )
- {
- return ( E_OUTOFMEMORY ) ;
- }
-
- // Do the query for the requested interface.
- hr = pObj->QueryInterface ( riid , ppv ) ;
-
- // If the interface is not supported, delete the IClassFactory
- // implementation instance.
- if ( FAILED ( hr ) )
- {
- delete pObj ;
- }
-
- return ( hr ) ;
- }
-
- /*----------------------------------------------------------------------
- FUNCTION : DllCanUnloadNow
- DISCUSSION :
- If there are no references ony objects that this DLL provides, than
- the DLL can be unloaded.
- PARAMETERS :
- None.
- RETURN :
- S_OK - The DLL can be unloaded.
- S_FALSE - The DLL still has referenced objects.
- ----------------------------------------------------------------------*/
- STDAPI DllCanUnloadNow ( void )
- {
- HRESULT hr ;
-
- // Check the global variables to see if there are any objects or
- // locks outstanding.
- if ( ( 0 == g_nObject ) && ( 0 == g_nLock ) )
- {
- hr = S_OK ;
- }
- else
- {
- hr == S_FALSE ;
- }
- return ( hr ) ;
- }
-
-
- /*----------------------------------------------------------------------
- FUNCTION : DllRegisterServer
- DISCUSSION :
- Implementation of sef-registration functionality.
- PARAMETERS : void
- RETURN :
- NOERROR if successful, SELFREG_E_CLASS otherwise.
- ----------------------------------------------------------------------*/
- STDAPI DllRegisterServer ( void )
- {
- BOOL fContinue = TRUE ;
- TCHAR szIfaceTestID [ gk_nMaxRegKeySize ] ;
- TCHAR szRootKey [ gk_nMaxRegKeySize ] ;
- TCHAR szModule [ _MAX_PATH ] ;
- TCHAR szTemp [ gk_nMaxRegKeySize ] ;
- WCHAR szwIfaceTestID [ gk_nMaxRegKeySize ] ;
-
- HRESULT hrRet = NOERROR ;
-
-
- // Root registry key names
- StringFromGUID2 ( CLSID_InterfaceTest , szwIfaceTestID , gk_nMaxRegKeySize );
- #ifdef _UNICODE
- lstrcpy ( szIfaceTestID , szwIfaceTestID ) ;
- #else
- wcstombs ( szIfaceTestID , szwIfaceTestID , gk_nMaxRegKeySize ) ;
- #endif
-
- lstrcpy ( szRootKey , gk_szCLSID ) ;
- lstrcat ( szRootKey , gk_szSlash ) ;
- lstrcat ( szRootKey , szIfaceTestID ) ;
-
- try
- {
- // Create ProgID keys
- MakeRegEntry( gk_szVerIfaceTestPRGID ,
- NULL ,
- gk_szIfaceTestObjectName ) ;
-
- MakeRegEntry( gk_szVerIfaceTestPRGID ,
- gk_szCLSID ,
- szIfaceTestID ) ;
-
-
- // Create VersionIndependentProgID keys
- MakeRegEntry( gk_szIfaceTestPRGID ,
- NULL ,
- gk_szIfaceTestObjectName ) ;
-
- MakeRegEntry( gk_szIfaceTestPRGID ,
- gk_szCurVer ,
- gk_szVerIfaceTestPRGID ) ;
-
- MakeRegEntry( gk_szIfaceTestPRGID ,
- gk_szCLSID ,
- szIfaceTestID ) ;
-
- // Create CLSID key entries
- wsprintf ( szTemp , _T ( "%s\\%s" ) , gk_szCLSID , szIfaceTestID ) ;
- MakeRegEntry( szTemp ,
- NULL ,
- gk_szIfaceTestObjectName ) ;
-
- MakeRegEntry( szTemp ,
- gk_szProgID ,
- gk_szVerIfaceTestPRGID ) ;
-
- MakeRegEntry( szTemp ,
- gk_szVersionIndependentProgID ,
- gk_szIfaceTestPRGID ) ;
-
- MakeRegEntry( szTemp ,
- gk_szNotInsertable ,
- NULL ) ;
-
- HINSTANCE hMod = GetModuleHandle( gk_szModuleID ) ;
- GetModuleFileName(hMod, szModule, sizeof(szModule)/sizeof(TCHAR));
-
- MakeRegEntry( szTemp ,
- gk_szInprocServer32 ,
- szModule ) ;
- }
- catch ( UINT nE )
- {
- if ( gk_nMakeRegExcept == nE )
- hrRet = SELFREG_E_CLASS ;
- else
- throw nE ;
- }
-
- return hrRet ;
-
- }
-
-
- /*----------------------------------------------------------------------
- FUNCTION : DllUnregisterServer
- DISCUSSION :
- Implementation of sef-registration functionality.
- PARAMETERS : void
- RETURN :
- NOERROR if successful, SELFREG_E_CLASS otherwise.
- ----------------------------------------------------------------------*/
- STDAPI DllUnregisterServer ( void )
- {
- BOOL fContinue = TRUE ;
- TCHAR szIfaceTestID [ gk_nMaxRegKeySize ] ;
- TCHAR szRootKey [ gk_nMaxRegKeySize ] ;
- TCHAR szTemp [ gk_nMaxRegKeySize ] ;
- WCHAR szwIfaceTestID [ gk_nMaxRegKeySize ] ;
-
- HRESULT hrRet = NOERROR ;
-
-
- // Root registry key names
- StringFromGUID2 ( CLSID_InterfaceTest , szwIfaceTestID , gk_nMaxRegKeySize );
- #ifdef _UNICODE
- lstrcpy ( szIfaceTestID , szwIfaceTestID ) ;
- #else
- wcstombs ( szIfaceTestID , szwIfaceTestID , gk_nMaxRegKeySize ) ;
- #endif
-
- lstrcpy ( szRootKey , gk_szCLSID ) ;
- lstrcat ( szRootKey , gk_szSlash ) ;
- lstrcat ( szRootKey , szIfaceTestID ) ;
-
- try
- {
- // Delete ProgID keys
- wsprintf ( szTemp , _T ( "%s\\%s" ) , gk_szIfaceTestPRGID , gk_szCurVer ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- wsprintf ( szTemp , _T ( "%s\\%s" ) , gk_szIfaceTestPRGID , gk_szCLSID ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , gk_szIfaceTestPRGID ) )
- throw gk_nDelRegExcept ;
-
- // Delete VersionIndependentProgID keys
- wsprintf ( szTemp , _T ( "%s\\%s" ) , gk_szVerIfaceTestPRGID , gk_szCLSID ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , gk_szVerIfaceTestPRGID ) )
- throw gk_nDelRegExcept ;
-
- // Delete CLSID key entries
- wsprintf ( szTemp , _T ( "%s\\%s\\%s" ) , gk_szCLSID , szIfaceTestID , gk_szProgID ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- wsprintf ( szTemp , _T ( "%s\\%s\\%s" ) , gk_szCLSID , szIfaceTestID , gk_szVersionIndependentProgID ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- wsprintf ( szTemp , _T ( "%s\\%s\\%s" ) , gk_szCLSID , szIfaceTestID , gk_szNotInsertable ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- wsprintf ( szTemp , _T ( "%s\\%s\\%s" ) , gk_szCLSID , szIfaceTestID , gk_szInprocServer32 ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- wsprintf ( szTemp , _T ( "%s\\%s" ) , gk_szCLSID , szIfaceTestID ) ;
- if ( ERROR_SUCCESS != RegDeleteKey ( HKEY_CLASSES_ROOT , szTemp ) )
- throw gk_nDelRegExcept ;
- }
- catch ( UINT nE )
- {
- if ( gk_nDelRegExcept == nE )
- hrRet = SELFREG_E_CLASS ;
- else
- throw nE ;
- }
-
- return hrRet ;
- }
-
-
-
- /*----------------------------------------------------------------------
- FUNCTION : MakeRegEntry
- DISCUSSION :
- Support function for the sef-registration functionality.
- PARAMETERS : void
- szKey Name of key under which to add the entry
- szEntryKey The name of the key in the new entry
- szEntryVal The string value to store for the new entry
- RETURN :
- TRUE if successful, FALSE otherwise.
- ----------------------------------------------------------------------*/
- BOOL MakeRegEntry ( LPCTSTR szKey ,
- LPCTSTR szEntryKey ,
- LPCTSTR szEntryVal )
- {
- HKEY hKey ;
- TCHAR szTempKey [ 256 ] ;
- BOOL fReturn = FALSE ;
-
- lstrcpy ( szTempKey , szKey ) ;
-
- if ( NULL != szEntryKey )
- {
- lstrcat ( szTempKey , gk_szSlash ) ;
- lstrcat ( szTempKey , szEntryKey ) ;
- }
-
- if ( ERROR_SUCCESS == RegCreateKeyEx ( HKEY_CLASSES_ROOT ,
- szTempKey ,
- 0 ,
- NULL ,
- REG_OPTION_NON_VOLATILE ,
- KEY_ALL_ACCESS ,
- NULL ,
- &hKey ,
- NULL ) )
- {
- if ( NULL != szEntryVal )
- {
- RegSetValueEx( hKey ,
- NULL ,
- 0 ,
- REG_SZ ,
- ( BYTE * ) szEntryVal ,
- ( lstrlen ( szEntryVal ) + 1 ) * sizeof ( TCHAR ) );
- }
-
- RegCloseKey ( hKey ) ;
-
- fReturn = TRUE ;
- }
- else
- throw gk_nMakeRegExcept ;
-
- return ( fReturn ) ;
-
- }
-
-
- /*----------------------------------------------------------------------
- FUNCTION : ObjectDestroyed
- DISCUSSION :
- The notification function that the object will call to let the DLL
- implementation that it is going away. If we didn't have this, then the
- DLL would never know the reference or lock count.
- PARAMETERS :
- None.
- RETURN :
- None.
- ----------------------------------------------------------------------*/
- void ObjectDestroyed ( void )
- {
- // Bump the count down.
- g_nObject-- ;
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: CIFaceTestClassFactory
- DISCUSSION :
- Constructor for the IClassFactory implementation class.
- PARAMETERS :
- None.
- RETURN :
- None.
- ----------------------------------------------------------------------*/
- CIFaceTestClassFactory :: CIFaceTestClassFactory ( )
- {
- m_nRef = 0L ;
- }
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: ~CIFaceTestClassFactory
- DISCUSSION :
- Destructor for the IClassFactory implementation class.
- PARAMETERS :
- None.
- RETURN :
- None.
- ----------------------------------------------------------------------*/
- CIFaceTestClassFactory :: ~CIFaceTestClassFactory ( )
- {
- }
-
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: QueryInterface
- DISCUSSION :
- The implementation of the IUnknown::QueryInterface function.
- PARAMETERS :
- riid - The IID of the interface requested.
- ppv - Receives the returned interface.
- RETURN :
- NOERROR - The requested interface is in ppv.
- E_NOINTERFACE - The requested interface is not implemented.
- ----------------------------------------------------------------------*/
- STDMETHODIMP CIFaceTestClassFactory :: QueryInterface ( REFIID riid ,
- PPVOID ppv )
- {
- // Always set the return interface pointer to NULL.
- *ppv = NULL ;
-
- // If the request of for the IUnknown or IClassFactory interface,
- // we can support it.
- if ( ( IID_IUnknown == riid ) || ( IID_IClassFactory == riid ) )
- {
- *ppv = this ;
- }
-
- // If the request was for an interface we know about, then AddRef
- // the interface.
- if ( NULL != *ppv )
- {
- ((LPUNKNOWN)*ppv)->AddRef ( ) ;
- return ( NOERROR ) ;
- }
-
- // The requested interface is not supported.
- return ( E_NOINTERFACE ) ;
- }
-
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: AddRef
- DISCUSSION :
- The implementation of the IUnknown::AddRef function.
- PARAMETERS :
- None.
- RETURN :
- The new reference count for diagnostic purposes only.
- ----------------------------------------------------------------------*/
- STDMETHODIMP_( ULONG ) CIFaceTestClassFactory :: AddRef ( void )
- {
- m_nRef++ ;
- return ( m_nRef ) ;
- }
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: Release
- DISCUSSION :
- The implementation of the IUnknown::Release function.
- PARAMETERS :
- None.
- RETURN :
- The new reference count for diagnostic purposes only.
- ----------------------------------------------------------------------*/
- STDMETHODIMP_( ULONG ) CIFaceTestClassFactory :: Release ( void )
- {
- m_nRef-- ;
- if ( 0L != m_nRef )
- {
- return ( m_nRef ) ;
- }
-
- delete this ;
- return ( 0L ) ;
- }
-
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: CreateInstance
- DISCUSSION :
- The implementation of the IClassFactory::CreateInstance function.
- PARAMETERS :
- pUnkOuter - Indicates if the object is being created as part of a
- aggregate. If not NULL, the controlling unknown.
- riid - Specified the IID of the interface the caller wants from
- the object.
- ppvObj - The interface storeage location.
- RETURN :
- CLASS_E_NOAGGREGATION - This object does not support aggregation.
- E_OUTOFMEMORY - Unable to allocate memory for the
- implementation class.
- E_UNEXPECTED - Unable to initialize the implementation
- class.
- NOERROR - All OK, Jumpmaster!
- ----------------------------------------------------------------------*/
- STDMETHODIMP CIFaceTestClassFactory ::
- CreateInstance ( LPUNKNOWN pUnkOuter ,
- REFIID riid ,
- PPVOID ppvObj )
- {
- // The pointer to the class object.
- PCIUnknown pObj ;
- HRESULT hr ;
-
- // Always NULL out the interface return location.
- *ppvObj = NULL ;
-
- // Verify that a controlling unknown asks for IUnknown. This
- // implementation does not support aggregation.
- if ( ( NULL != pUnkOuter ) && ( IID_IUnknown != riid ) )
- {
- return ( CLASS_E_NOAGGREGATION ) ;
- }
-
- // Create the object passing function to notify on destruction.
- pObj = new CIUnknown ( pUnkOuter , ObjectDestroyed ) ;
-
- // If we could not allocate the implementation class, kick out.
- if ( NULL == pObj )
- {
- return ( E_OUTOFMEMORY ) ;
- }
-
- // Call the implementation initialization function. If if fails,
- // we will return E_UNEXPECTED to indicate we had a major problem.
- if ( FALSE == pObj->Init ( ) )
- {
- return ( E_UNEXPECTED ) ;
- }
-
- // Now do the query interface for the requested interface.
- hr = pObj->QueryInterface ( riid , ppvObj ) ;
-
- //Kill the object if initial creation or Init failed.
- if ( FAILED ( hr ) )
- {
- delete pObj ;
- }
- else
- {
- // Bump up the number of objects created.
- g_nObject++ ;
- }
-
- return ( hr ) ;
- }
-
- /*----------------------------------------------------------------------
- FUNCTION : CIFaceTestClassFactory :: LockServer
- DISCUSSION :
- The implementation of the IClassFactory::LockServer function.
- PARAMETERS :
- fLock - If TRUE, the lock count is incremented. If false, the lock
- count is decremented.
- RETURN :
- NOERROR.
- ----------------------------------------------------------------------*/
- STDMETHODIMP CIFaceTestClassFactory :: LockServer ( BOOL fLock )
- {
- if ( TRUE == fLock )
- {
- g_nLock++ ;
- }
- else
- {
- g_nLock-- ;
- }
-
- return ( NOERROR ) ;
- }
-
-