DLLUnregister Server in MFC based COM applications

MFC usually saves you a lot of time when impelmenting COM components. For example, MFC-based COM dll projects generated with AppWizard automatically provides you with the implementation of DllRegisterServer function. However, there is no DllUnregisterServer in the AppWizard generated dll. This, generally, is not acceptable, because every COM dll should support self-registration as well as self-unregistration.

MFC-based implementation of DllRegisterServer() calls COleObjectFactory::UpdateRegistryAll(). This method has an undocumented parameter - (BOOL bRegister = TRUE) - so, we can expect that calling COleObjectFactory::UpdateRegistry(FALSE) will unregister COM dll for us. This is, unfortunately, not the case. Looking at the source code quikly tells us, that COleObjectFactory::UpdateRegistryAll(BOOL bRegister) calls COleObjectFactory::UpdateRegistry(BOOL bRegister) passing the same value of BOOL parameter, but the implementation of COleObjectFactory::UpdateRegistry(BOOL bRegister) calls UpdateRegistry(LPCTSTR lpszProgID) which registers dll only if bRegister is TRUE, otherwise it just does nothing!

Therefore, it is still necessary to write our own DllUnregisterServer(). The code below is a ready and easy to use implementation of DllUnregisterServer() for MFC-based COM dlls. To use it:

- create a file DllUnregisterServer_MFC_Impl.inl

- copy/paste the code below into this file

- add the following line at the end of the main dll .cpp file (dll_name.cpp):


#include "DllUnregisterServer_MFC_Impl.inl"

- add the following line to the EXPORTS section of the dll .def file (dll_name.def):

 
DllUnregisterServer PRIVATE

That's it! Now you can use "regsvr32 /u dll_name.dll" for dll unregistration!

This code was tested with VC++ 5.0, VC++ 5.0 SP3, VC++ 6.0 (yeah, 6.0 still doesn't provide DllUnregisterServer for free) in ANSI builds. There should be no problems with UNICODE as well.


//**************************************************************************
// Date : 11.15.98
// Header : DllUnregisterServer_MFC_Impl.inl
//
// Desc.:	DllUnregisterServer() helper for the inproc servers that were
//		registered via MFC's COleObjectFactory::UpdateRegistryAll()
//
// Usage:
//			Add '#include "DllUnregisterServer_MFC_Impl.inl"' to the end of
//		the main dll file (i.e. dll_name.cpp).
//
//			Add 'DllUnregisterServer	PRIVATE' to EXPORTS section of the
//		dll_name.def.
//
// Caution:
//			Code below uses undocumented, internal MFC data structures
//		and functions. Therefore, probably, it will be necessary to modify
//		it, according to the changes in the future versions of MFC.
//			Code below is based on the COleObjectFactory::UpdateRegistryAll(),
//		in src\olefact.cpp. (src\olereg.cpp - is actual implementation of
//		all registry work).
//**************************************************************************
#include "stdafx.h"

// workaround MFC bug - no #ifndef/#endif for afximpl.h header
#if !defined(CRIT_OBJECTFACTORYLIST)
#include <..\src\afximpl.h>
#endif		//!CRIT_OBJECTFACTORYLIST
//**************************************************************************
static HRESULT UnregisterCOMObject(REFCLSID p_clsid)
{
	LPOLESTR t_wzProgID(NULL);

	// get ProgID from CLSID and unregister...
	HRESULT t_hr = ::ProgIDFromCLSID(p_clsid, &t_wzProgID);
	if(FAILED(t_hr))
		return t_hr;

	// convert OLESTR to LPTSTR
	CString t_strProgID(t_wzProgID);
	LPCTSTR t_szProgID = t_strProgID.operator LPCTSTR();

	// free memory
	::CoTaskMemFree(t_wzProgID);

	// unregister...
	if(AfxOleUnregisterServerClass(p_clsid,
				       t_szProgID,
				       t_szProgID,
				       t_szProgID,
				       OAT_DISPATCH_OBJECT))
		return S_OK;
	else
		return E_FAIL;
}
//**************************************************************************
// by exporting DllUnregisterServer, you can use regsvr.exe
STDAPI DllUnregisterServer(void)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());


	AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

	AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
	for(COleObjectFactory* pFactory = pModuleState->m_factoryList;
		pFactory != NULL;
		pFactory = pFactory->m_pNextFactory)
	{
		HRESULT t_hr = UnregisterCOMObject(pFactory->GetClassID());
		if(FAILED(t_hr))
		{
			AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
			return t_hr;
		}
	}
	AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);

#ifdef _AFXDLL
	AfxLockGlobals(CRIT_DYNLINKLIST);
	// register extension DLL factories
	for(CDynLinkLibrary* pDLL = pModuleState->m_libraryList;
		pDLL != NULL;
		pDLL = pDLL->m_pNextDLL)
	{
		for(pFactory = pDLL->m_factoryList;
			pFactory != NULL;
			pFactory = pFactory->m_pNextFactory)
		{
			HRESULT t_hr = UnregisterCOMObject(pFactory->GetClassID());
			if(FAILED(t_hr))
			{
				AfxUnlockGlobals(CRIT_DYNLINKLIST);
				return t_hr;
			}
		}
	}
	AfxUnlockGlobals(CRIT_DYNLINKLIST);
#endif

	return S_OK;
}
//**************************************************************************
// end of DllUnregisterServer_MFC_Impl.inl

Download source - [DllUnregisterServer_MFC_Impl.zip] - 1.3 KB



Comments

  • could we use these lines for this ?

    Posted by Legacy on 07/02/2002 12:00am

    Originally posted by: Q1


    STDAPI DllRegisterServer(void)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    COleObjectFactory::UnregisterAll();
    return S_OK;
    }

    Reply
  • Thnaks.Good Job done

    Posted by Legacy on 06/01/2002 12:00am

    Originally posted by: Rajeshwar Samyal

    THanx buddy.Your code has helped me alot.

    Reply
  • You're the man!

    Posted by Legacy on 03/16/2002 12:00am

    Originally posted by: Chris Norris

    Thanks for the source! I have written many DLL's that I could never unregister, and this fixes everything! I'm so glad I found this Web page. Cheers!

    Reply
  • Thanks very much!!

    Posted by Legacy on 12/10/2001 12:00am

    Originally posted by: Chuck Stephens

    This code was exactly what I needed. I put it in my MFC dll and it works perfectly.

    Reply
  • It is just what I need.

    Posted by Legacy on 12/11/2000 12:00am

    Originally posted by: Irving Fu

    Thank you for your code. I'm just wondering why Microsoft didn't supply DllUnregisterServer() function with MFC.

    Reply
  • Question relating to DllUnregisterServer for MFC-based COM dlls.

    Posted by Legacy on 03/07/2000 12:00am

    Originally posted by: Viseth Peang

    First I like to thank the author for posting this article. I use this code to unregister my dlls with little modification to the original code. The dll unregister fine from the registry, but it still thinks that the dll is in use. When I make a change to the dll I have to reboot for the dll to compile after I tested it. Has anyone ran into this particular problem, or am I doing something totally wrong?

    Environment: Windows NT4 server sp5, VC++ 5 sp3.

    Any comments or suggestions are appreciated.

    Thanks

    Viseth

    Reply
  • Good Job

    Posted by Legacy on 10/21/1999 12:00am

    Originally posted by: Ning Lin

    Cool! This is what I am looking for.

    Thanks!
    --Ning

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 16, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you starting an on-premise-to-cloud data migration project? Have you thought about how much space you might need for your online platform or how to handle data that might be related to users who no longer exist? If these questions or any other concerns have been plaguing you about your migration project, check out this eSeminar. Join our speakers Betsy Bilhorn, VP, Product Management at Scribe, Mike Virnig, PowerSucess Manager and Michele …

  • This ESG study by Mark Peters evaluated a common industry-standard disk VTl deduplication system (with 15:1 reduction ratio) versus a tape library with LTO-5, drives with full nightly backups, over a five-year period.  The scenarios included replicated systems and offsite tape vaults.  In all circumstances, the TCO for VTL with deduplication ranged from about 2 to 4 times more expensive than the LTO-5 tape library TCO. The paper shares recent ESG research and lots more. 

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds