Click here to Skip to main content
15,889,315 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,
I am quite new I am trying to create COM class to be able to access it via VB.NET. The code compiles fine,but on createObject returns null (no class). The main conde is taken from codeguru, but I've tried to simplify interface (don't want to be completely visible via object browser).
Could anyone help me to solve this?

C++
//
//NewCamdFactory.h
//
//Contains the declaration for the class factory for our super-fast
//addition algorithm COM object
//

extern long g_nComObjsInUse;

class CNewCamdFactory : public IClassFactory
    {

    public:
    CNewCamdFactory()
        {
        m_nRefCount=0;
        //
        //increment the global count
        //
        InterlockedIncrement(&g_nComObjsInUse);
        }

    ~CNewCamdFactory()
        {
        //
        //decrement the global count
        //
        InterlockedDecrement(&g_nComObjsInUse);
        }


    //IUnknown methods are implemented here
    HRESULT __stdcall QueryInterface(
                                REFIID riid , 
                                void **ppObj);


    ULONG   __stdcall AddRef()
        {
        return InterlockedIncrement(&m_nRefCount) ;
        }

    ULONG   __stdcall Release()
        {
        long nRefCount=0;
        nRefCount=InterlockedDecrement(&m_nRefCount) ;
        if (nRefCount == 0) delete this;
        return nRefCount;
        }


	// Interface IClassFactory
	virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
	                                         const IID& iid,
	                                         void** ppv) ;
	virtual HRESULT __stdcall LockServer(BOOL bLock) ; 

    private:
    long m_nRefCount;
    };



C++
//
//NewCamdFactory.cpp
//
//Contains the method body for the class factory for our super-fast
//addition algorithm COM object
//
#include    <objbase.h>
#include    "NewCamdFactory.h"
#include    "NewCamdLib.h"




HRESULT __stdcall CNewCamdFactory::QueryInterface(
                                const IID& iid, 
                                void** ppv)
    {    
	if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
	    {
		*ppv = static_cast<IClassFactory*>(this) ; 
	    }
	else
	    {
		*ppv = NULL ;
		return E_NOINTERFACE ;
	    }
	reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
	return S_OK ;
    }


HRESULT __stdcall CNewCamdFactory::LockServer(BOOL bLock) 
    {
	return E_NOTIMPL;
    }

HRESULT __stdcall CNewCamdFactory::CreateInstance(IUnknown* pUnknownOuter,
                                           const IID& iid,
                                           void** ppv) 
    {
    //
    //This method lets the client manufacture components en masse
    //The class factory provides a mechanism to control the way
    //the component is created. Within the class factory the 
    //author of the component may decide to selectivey enable
    //or disable creation as per license agreements 
    //
    //

	// Cannot aggregate.
	if (pUnknownOuter != NULL)
	    {
		return CLASS_E_NOAGGREGATION ;
	    }

    //
	// Create an instance of the component.
    //
	CNewCamdLib* pObject = new CNewCamdLib ;
	if (pObject == NULL)
	    {
		return E_OUTOFMEMORY ;
	    }

    //
	// Get the requested interface.
    //
	return pObject->QueryInterface(iid, ppv) ;
    }


C++
//
//NewCamdGuid.h
//
#ifndef __NewCamdGuid_h__
#define __NewCamdGuid_h__

// {92E7A9C2-F4CB-11d4-825D-00104B3646C0}
static const GUID CLSID_NewCamdObject =
{ 0x92f7a9cc, 0xf4cb, 0x11d4, { 0x82, 0x6d, 0x0, 0x17, 0x4b, 0x36, 0x46, 0xc0 } };

// {D518B0BF-3EE1-4976-9B6A-9F3443A2A186}
static const GUID IID_IStatus =
{ 0xd518b0bf, 0x3ee1, 0x4976, {0x9b, 0x6a, 0x9f, 0x34, 0x43, 0xa2, 0xa1, 0x86 } };

struct IStatus : public IUnknown
{
    virtual HRESULT __stdcall Register(int RegisterCode, int Licence) = 0;
};

#endif




C++
//
//Exports.cpp
//Contains the implementation of the COM specified exported functions
//DlLRegisterServer, DllUnRegisterServer, DllGetClassObject, 
//DllCanUnloadNow
//

#include    <objbase.h>
#include    "NewCamdLib.h"
#include    "NewCamdFactory.h"
#include    "NewCamdGuid.h"

HMODULE g_hModule=NULL;
long g_nComObjsInUse=0;
///////////////////////////////////////////////////////////////////////////////

BOOL APIENTRY DllMain(HANDLE hModule,
                      DWORD dwReason,
                      void* lpReserved)
    {
	if (dwReason == DLL_PROCESS_ATTACH)
        {
		g_hModule = (HMODULE)hModule ;
        }
	return TRUE ;
    }



///////////////////////////////////////////////////////////////////////////////

STDAPI DllGetClassObject(const CLSID& clsid,
                         const IID& iid,
                         void** ppv)
    {
    //
    //Check if the requested COM object is implemented in this DLL
    //There can be more than 1 COM object implemented in a DLL
    //

    if (clsid == CLSID_NewCamdObject)
        {
        //
        //iid specifies the requested interface for the factory object
        //The client can request for IUnknown, IClassFactory,
        //IClassFactory2
        //
        CNewCamdFactory *pNewCamd = new CNewCamdFactory;
        if (pNewCamd == NULL)
            return E_OUTOFMEMORY;
        else
            {
            return pNewCamd->QueryInterface(iid , ppv);
            }
        }
    

    //
    //if control reaches here then that implies that the object
    //specified by the user is not implemented in this DLL
    //

    return CLASS_E_CLASSNOTAVAILABLE;
    }



///////////////////////////////////////////////////////////////////////////////

STDAPI DllCanUnloadNow()
    {
    //
    //A DLL is no longer in use when it is not managing any existing objects
    // (the reference count on all of its objects is 0). 
    //We will examine the value of g_nComObjsInUse 
    //
    
    if (g_nComObjsInUse == 0)
        {
        return S_OK;
        }
    else
        {
        return S_FALSE;
        }

    }

///////////////////////////////////////////////////////////////////////////////


Exports.Def

C++
;
;contains the list of functions that are being exported from this DLL
;

DESCRIPTION     "NewCamdD COM object"
LIBRARY         "NewCamdLib"

EXPORTS
                DllGetClassObject       PRIVATE
                DllCanUnloadNow         PRIVATE
                DllRegisterServer       PRIVATE
                DllUnregisterServer     PRIVATE



Registry.h
C++
#ifndef __Registry_H__
#define __Registry_H__
//
// Registry.h
//   - Helper functions registering and unregistering a component.
//

// This function will register a component in the Registry.
// The component calls this function from its DllRegisterServer function.
HRESULT RegisterServer(HMODULE hModule, 
                       const CLSID& clsid, 
                       const char* szFriendlyName,
                       const char* szVerIndProgID,
                       const char* szProgID) ;

// This function will unregister a component.  Components
// call this function from their DllUnregisterServer function.
HRESULT UnregisterServer(const CLSID& clsid,
                         const char* szVerIndProgID,
                         const char* szProgID) ;

#endif


C++
//
//Registry.cpp
//
//Implementation for DllRegisterServer,DllUnregisterServer
//Contains code to write COM server data into the registry and 
//also removing the data that had been written into the registry 
//by this module.
//

#include    <windows.h>
#include    <objbase.h>

#include    "NewCamDGuid.h"
#define     NewCamDProgId    "TomSoft.NewCamDLibrary"
extern HMODULE g_hModule;


BOOL   HelperWriteKey(
                            HKEY roothk,
                            const char *lpSubKey,
                            LPCTSTR val_name, 
                            DWORD dwType,
                            void *lpvData, 
                            DWORD dwDataSize)
    {
    //
    //Helper function for doing the registry write operations
    //
    //roothk:either of HKCR, HKLM, etc

    //lpSubKey: the key relative to 'roothk'
    
    //val_name:the key value name where the data will be written
    
    //dwType:the type of data that will be written ,REG_SZ,REG_BINARY, etc.
    
    //lpvData:a pointer to the data buffer
    
    //dwDataSize:the size of the data pointed to by lpvData
    //
    //

    HKEY hk;
    if (ERROR_SUCCESS != RegCreateKey(roothk,lpSubKey,&hk) ) return FALSE;

    if (ERROR_SUCCESS != RegSetValueEx(hk,val_name,0,dwType,(CONST BYTE *)lpvData,dwDataSize)) return FALSE;
    
    if (ERROR_SUCCESS != RegCloseKey(hk))   return FALSE;
    return TRUE;
        
    }



///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////

HRESULT  __stdcall DllRegisterServer(void)
    {
    //
    //As per COM guidelines, every self installable COM inprocess component
    //should export the function DllRegisterServer for printing the 
    //specified information to the registry
    //
    //

    WCHAR *lpwszClsid;
    char szBuff[MAX_PATH]="";
    char szClsid[MAX_PATH]="", szInproc[MAX_PATH]="",szProgId[MAX_PATH];
    char szDescriptionVal[256]="";

    StringFromCLSID(
            CLSID_NewCamdObject,
            &lpwszClsid);
    
    wsprintf(szClsid,"%S",lpwszClsid);
    wsprintf(szInproc,"%s\\%s\\%s","clsid",szClsid,"InprocServer32");
    wsprintf(szProgId,"%s\\%s\\%s","clsid",szClsid,"ProgId");


    //
    //write the default value 
    //
    wsprintf(szBuff,"%s","Fast Addition Algorithm");
    wsprintf(szDescriptionVal,"%s\\%s","clsid",szClsid);

    HelperWriteKey (
                HKEY_CLASSES_ROOT,
                szDescriptionVal,
                NULL,//write to the "default" value
                REG_SZ,
                (void*)szBuff,
                lstrlen(szBuff)
                );


    //
    //write the "InprocServer32" key data
    //
    GetModuleFileName(
                g_hModule,
                szBuff,
                sizeof(szBuff));
    HelperWriteKey (
                HKEY_CLASSES_ROOT,
                szInproc,
                NULL,//write to the "default" value
                REG_SZ,
                (void*)szBuff,
                lstrlen(szBuff)
                );

    //
    //write the "ProgId" key data under HKCR\clsid\{---}\ProgId
    //
    lstrcpy(szBuff,NewCamDProgId);
    HelperWriteKey (
                HKEY_CLASSES_ROOT,
                szProgId,
                NULL,
                REG_SZ,
                (void*)szBuff,
                lstrlen(szBuff)
                );


    //
    //write the "ProgId" data under HKCR\CodeGuru.FastAddition
    //
    wsprintf(szBuff,"%s","OpenSSL Algorithm support for NewCamd");
    HelperWriteKey (
                HKEY_CLASSES_ROOT,
                NewCamDProgId,
                NULL,
                REG_SZ,
                (void*)szBuff,
                lstrlen(szBuff)
                );


    wsprintf(szProgId,"%s\\%s",NewCamDProgId,"CLSID");
    HelperWriteKey (
                HKEY_CLASSES_ROOT,
                szProgId,
                NULL,
                REG_SZ,
                (void*)szClsid,
                lstrlen(szClsid)
                );

    return 1;

    }


///////////////////////////////////////////////////////////////////////////////

HRESULT  __stdcall DllUnregisterServer(void)
    {
    //
    //As per COM guidelines, every self removable COM inprocess component
    //should export the function DllUnregisterServer for erasing all the 
    //information that was printed into the registry
    //
    //

    char szKeyName[256]="",szClsid[256]="";
    WCHAR *lpwszClsid;

    

    //
    //delete the ProgId entry
    //
    wsprintf(szKeyName,"%s\\%s",NewCamDProgId,"CLSID");
    RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);
    RegDeleteKey(HKEY_CLASSES_ROOT,NewCamDProgId);


    //
    //delete the CLSID entry for this COM object
    //
    StringFromCLSID(
            CLSID_NewCamdObject,
            &lpwszClsid);
    wsprintf(szClsid,"%S",lpwszClsid);
    wsprintf(szKeyName,"%s\\%s\\%s","CLSID",szClsid,"InprocServer32");
    RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);

    wsprintf(szKeyName,"%s\\%s\\%s","CLSID",szClsid,"ProgId");
    RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);

    wsprintf(szKeyName,"%s\\%s","CLSID",szClsid);
    RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);

    return 1;

    }



NewCamdLib.h

C++
#include	"NewCamdGuid.h"

// This class is exported from the NewCamdLib.dll
extern long g_nComObjsInUse;
class CNewCamdLib: public IStatus {
public:
	//CNewCamdLib(void);
	HRESULT __stdcall CNewCamdLib::Register(int RegisterCode, int Licence);

    //IUnknown methods are implemented here
    HRESULT __stdcall QueryInterface(
                                REFIID riid , 
                                void **ppObj);


    ULONG   __stdcall AddRef()
        {
        return InterlockedIncrement(&m_nRefCount) ;
        }

    ULONG   __stdcall Release()
        {     
        long nRefCount=0;
        nRefCount=InterlockedDecrement(&m_nRefCount) ;
        if (nRefCount == 0) delete this;
        return nRefCount;
        }

	
    CNewCamdLib()
        {
        //
        //constructor
        //

        m_nRefCount=0;
		m_reg = false;
        //
        //increment the global count
        //
        InterlockedIncrement(&g_nComObjsInUse);
        }


    ~CNewCamdLib()
        {
        //
        //destructor
        //decerement the global object count
        InterlockedDecrement(&g_nComObjsInUse);
            
        }
private:
	bool m_reg;
    long m_nRefCount;   //for managing the reference count
};



newCamdLib.cpp file which returns interface and probably null:

C++
// NewCamdLib.cpp : Defines the exported functions for the DLL application.
//

#include    <objbase.h>
#include    "NewCamdLib.h"
#include    "NewCamdGuid.h"

HRESULT __stdcall  CNewCamdLib::Register(int RegisterCode, int Licence)
{
    if (RegisterCode == 888 && Licence == 111)
    {
        m_reg = true;
        return 1;
    }
    return 0;
}


HRESULT __stdcall CNewCamdLib::QueryInterface(
                                    REFIID riid ,
                                    void **ppObj)
    {
    if (riid == IID_IUnknown)
        {
        *ppObj =static_cast<IStatus *> (this) ;
        ((IUnknown *)(*ppObj))->AddRef();
        return S_OK;
        }
    if (riid == IID_IStatus)
        {
        *ppObj =static_cast<IStatus *> (this) ;
        ((IUnknown *)(*ppObj))->AddRef();
        return S_OK;
        }

    //
    //if control reaches here then , let the client know that
    //we do not satisfy the required interface
    //

    *ppObj = NULL ;
    return E_NOINTERFACE ;
    }




My VB6 testing code:

VB
Option Explicit

Private Sub Form_Load()
Dim obj As Object, ret As Integer

Set obj = CreateObject("TomSoft.NewCamDLibrary")
Dim lbCode As Long, Licence As Long
Licence = 11111
lbCode = 3333
ret = obj.Register(lbCode, Licence)
MsgBox "Returned = " & ret
End Sub
Posted
Comments
Mehdi Gholam 7-Jan-12 14:16pm    
Please do not code dump.
Sergey Alexandrovich Kryukov 7-Jan-12 15:00pm    
Not a question; this is pretty useless code dump. What's the problem?
--SA
Tomazas77 7-Jan-12 15:33pm    
As I said, it compiles then code, but using COM interface class is not returned.
VB6 for example return error:
Run-time error 424: Object required on line
Set obj = CreateObject("TomSoft.NewCamDLibrary")

VB.NET return on same line:
Cannot create ActiveX component.
Sergey Alexandrovich Kryukov 7-Jan-12 16:05pm    
OK, there is no such object, that's it. Check up things.
--SA
Tomazas77 7-Jan-12 16:41pm    
I've modified then CNewCamdLib::QueryInterface code and I may thing there is an error in there, but I am not familiar with COM objects especially in C++.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900