A complete com demo (C ++ language description)

Source: Internet
Author: User

For beginner COM, a complete example is still quite troublesome. Recently I have been studying and learned the basic principles through my own exploration. Here we will explain a simple string example step by step.

Source code download

1. Create a project

First, use vs2010 to create a project. Select an empty project and name it mycom.

2. Create an Interface Class

#ifndef IString_h__#define IString_h__#include <Windows.h>#include <Unknwn.h>#include <ObjBase.h>extern "C" const GUID IID_IString;class IString : public IUnknown{public:virtual HRESULT STDMETHODCALLTYPE SetString(char*) = 0;virtual HRESULT STDMETHODCALLTYPE GetString(char*, long) = 0;virtual HRESULT STDMETHODCALLTYPE AboutMessage() = 0;};#endif // IString_h__

3. Create component classes

#ifndef String_h__#define String_h__#include "IString.h"class String :public IString{public:String();~String();public://IUkown FunctionHRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,LPVOID *ppv);ULONG   STDMETHODCALLTYPE AddRef();ULONG   STDMETHODCALLTYPE Release();//IString FunctionHRESULT STDMETHODCALLTYPE SetString(char* chBuf);HRESULT STDMETHODCALLTYPE GetString(char* chBuf, long cLength);HRESULT STDMETHODCALLTYPE AboutMessage();protected:ULONG m_Ref;char buffer[80];};#endif // String_h__

3. Define a factory

#ifndef CFactory_h__#define CFactory_h__#include <Unknwn.h>class CFactory : public IClassFactory{public:CFactory();~CFactory();//IUnknown membersHRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void **ppv);ULONGSTDMETHODCALLTYPE AddRef();ULONGSTDMETHODCALLTYPE Release();//IClassFactory membersHRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *, const IID& iid, void **ppv);HRESULT STDMETHODCALLTYPE LockServer(BOOL bIsLocck);protected:ULONG m_Ref;};#endif // CFactory_h__

4. factory implementation

#include "CFactory.h"#include "String.h"extern ULONG g_LockNumber;extern ULONG g_StringNumber;CFactory::CFactory(){m_Ref = 0;}CFactory::~CFactory(){}HRESULT CFactory::QueryInterface(const IID& iid, void **ppv){if (iid == IID_IUnknown){*ppv = (IUnknown*)this;((IUnknown*)(*ppv))->AddRef();}else if(iid == IID_IClassFactory){*ppv = (IClassFactory*)this;((IClassFactory*)(*ppv))->AddRef();}else{*ppv = NULL;return E_NOINTERFACE;}return S_OK;}ULONG CFactory::AddRef(){m_Ref++;return m_Ref;}ULONG CFactory::Release(){m_Ref--;if (m_Ref == 0){delete this;return 0;}return m_Ref;}HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv){HRESULT hr;String *pObj;*ppv = NULL;hr = E_OUTOFMEMORY;if(NULL != pUnknownOuter)return CLASS_E_NOAGGREGATION;pObj = new String();if(NULL == pObj)return hr;hr = pObj->QueryInterface(iid,ppv);if (hr != S_OK){g_StringNumber--;delete pObj;}return S_OK;}HRESULT CFactory::LockServer(BOOL bIsLock){if (bIsLock)g_LockNumber++;elseg_LockNumber--;return S_OK;}

5. Export the function def File

LIBRARY "MyCom"EXPORTS    ; Explicit exports can go hereDllGetClassObject PRIVATEDllRegisterServer PRIVATEDllUnregisterServer PRIVATEDllCanUnloadNow  PRIVATE

6. Component Registration

#ifndef __Registry_H__#define __Registry_H__//// Registry.h//   - Helper functions registering and unregistering a component.////   - These helper functions were borrowed and modifed from//     Dale Rogerson's book Inside COM.// This function will register a component in the Registry.// DllRegisterServer function should call this function.HRESULT RegisterServer(const CLSID& clsid,                       const char *szFileName,                        const char* szProgID,                       const char* szDescription,                       const char* szVerIndProgID) ;// This function will unregister a component.  Components// DllUnregisterServer function should call this function.HRESULT UnregisterServer(const CLSID& clsid,                         const char* szProgID,                         const char* szVerIndProgID) ;#endif

7. Component registration implementation

//// Registry.cpp//#include <objbase.h>#include <assert.h>#include "Registry.h"//////////////////////////////////////////////////////////// Internal helper functions prototypes////   - These helper functions were borrowed and modifed from//     Dale Rogerson's book Inside COM.// Set the given key and its value.BOOL SetKeyAndValue(const char* pszPath,                    const char* szSubkey,                    const char* szValue) ;// Convert a CLSID into a char string.void CLSIDtoString(const CLSID& clsid,                  char* szCLSID,                 int length) ;// Delete szKeyChild and all of its descendents.LONG DeleteKey(HKEY hKeyParent, const char* szKeyString) ;//////////////////////////////////////////////////////////// Constants//// Size of a CLSID as a stringconst int CLSID_STRING_SIZE = 39 ;///////////////////////////////////////////////////////////// Public function implementation////// Register the component in the registry.//HRESULT RegisterServer(const CLSID& clsid,         // Class ID                       const char *szFileName,     // DLL module handle                       const char* szProgID,       //   IDs                       const char* szDescription,  // Description String                       const char* szVerIndProgID) // optional{    // Convert the CLSID into a char.    char szCLSID[CLSID_STRING_SIZE] ;    CLSIDtoString(clsid, szCLSID, sizeof(szCLSID)) ;    // Build the key CLSID\\{...}    char szKey[64] ;    strcpy_s(szKey, "CLSID\\") ;    strcat_s(szKey, szCLSID) ;      // Add the CLSID to the registry.    SetKeyAndValue(szKey, NULL, szDescription) ;    // Add the server filename subkey under the CLSID key.    SetKeyAndValue(szKey, "InprocServer32", szFileName) ;    // Add the ProgID subkey under the CLSID key.    if (szProgID != NULL) {        SetKeyAndValue(szKey, "ProgID", szProgID) ;        SetKeyAndValue(szProgID, "CLSID", szCLSID) ;    }    if (szVerIndProgID) {        // Add the version-independent ProgID subkey under CLSID key.        SetKeyAndValue(szKey, "VersionIndependentProgID",                       szVerIndProgID) ;        // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.        SetKeyAndValue(szVerIndProgID, NULL, szDescription) ;         SetKeyAndValue(szVerIndProgID, "CLSID", szCLSID) ;        SetKeyAndValue(szVerIndProgID, "CurVer", szProgID) ;        // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.        SetKeyAndValue(szProgID, NULL, szDescription) ;         SetKeyAndValue(szProgID, "CLSID", szCLSID) ;    }    return S_OK ;}//// Remove the component from the registry.//HRESULT UnregisterServer(const CLSID& clsid,      // Class ID                      const char* szProgID,       //   IDs                      const char* szVerIndProgID) // Programmatic{    // Convert the CLSID into a char.    char szCLSID[CLSID_STRING_SIZE] ;    CLSIDtoString(clsid, szCLSID, sizeof(szCLSID)) ;    // Build the key CLSID\\{...}    char szKey[64] ;    strcpy_s(szKey, "CLSID\\") ;    strcat_s(szKey, szCLSID) ;    // Delete the CLSID Key - CLSID\{...}    LONG lResult = DeleteKey(HKEY_CLASSES_ROOT, szKey) ;    // Delete the version-independent ProgID Key.    if (szVerIndProgID != NULL)        lResult = DeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;    // Delete the ProgID key.    if (szProgID != NULL)        lResult = DeleteKey(HKEY_CLASSES_ROOT, szProgID) ;    return S_OK ;}/////////////////////////////////////////////////////////////// Internal helper functions//// Convert a CLSID to a char string.void CLSIDtoString(const CLSID& clsid,                 char* szCLSID,                 int length){    assert(length >= CLSID_STRING_SIZE) ;    // Get CLSID    LPOLESTR wszCLSID = NULL ;    HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;    assert(SUCCEEDED(hr)) ;    // Covert from wide characters to non-wide.    wcstombs(szCLSID, wszCLSID, length) ;    // Free memory.    CoTaskMemFree(wszCLSID) ;}//// Delete a key and all of its descendents.//LONG DeleteKey(HKEY hKeyParent,           // Parent of key to delete               const char* lpszKeyChild)  // Key to delete{    // Open the child.    HKEY hKeyChild ;    LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,                             KEY_ALL_ACCESS, &hKeyChild) ;    if (lRes != ERROR_SUCCESS)    {        return lRes ;    }    // Enumerate all of the decendents of this child.    FILETIME time ;    char szBuffer[256] ;    DWORD dwSize = 256 ;    while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,                        NULL, NULL, &time) == S_OK)    {        // Delete the decendents of this child.        lRes = DeleteKey(hKeyChild, szBuffer) ;        if (lRes != ERROR_SUCCESS)        {            // Cleanup before exiting.            RegCloseKey(hKeyChild) ;            return lRes;        }        dwSize = 256 ;    }    // Close the child.    RegCloseKey(hKeyChild) ;    // Delete this child.    return RegDeleteKey(hKeyParent, lpszKeyChild) ;}//// Create a key and set its value.//BOOL SetKeyAndValue(const char* szKey,                    const char* szSubkey,                    const char* szValue){    HKEY hKey;    char szKeyBuf[1024] ;    // Copy keyname into buffer.    strcpy(szKeyBuf, szKey) ;    // Add subkey name to buffer.    if (szSubkey != NULL)    {        strcat(szKeyBuf, "\\") ;        strcat(szKeyBuf, szSubkey ) ;    }    // Create and open key and subkey.    long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,                                  szKeyBuf,                                   0, NULL, REG_OPTION_NON_VOLATILE,                                  KEY_ALL_ACCESS, NULL,                                   &hKey, NULL) ;    if (lResult != ERROR_SUCCESS)    {        return FALSE ;    }    // Set the Value.    if (szValue != NULL)    {        RegSetValueEx(hKey, NULL, 0, REG_SZ,                       (BYTE *)szValue,                       strlen(szValue)+1) ;    }    RegCloseKey(hKey) ;    return TRUE ;}

8. Introduction function and component function implementation

# Include "cfactory. H "# include" registry. H "# include" string. H "ulong g_locknumber = 0; ulong g_stringnumber = 0; // {struct} extern" C "const guid clsid_string = {0x913aae18, 0x1d57, 0x4868, {0xaf, 0x2f, 0xb4, 0x7d, 0x32, 0x16, 0x3e, 0x8f }}; // {struct} extern "C" const guid iid_istring = {0x416dc65f, 0x48e2, 0x436a, {0xba, 0x34, 0xfc, 0x0, 0xac, 0x3d, 0xa5, 0x98 }}; hmodule g_hmodule = 0; bool apientry dllmain (hmodule, DWORD ul_reason_for_call, lpvoid lpreserved) {g_hmodule = hmodule; return true ;} extern "C" hresult stdmethodcalltype encode () {If (g_locknumber = 0) & (g_stringnumber) return s_ OK; elsereturn s_false;} extern "C" hresult stdmethodcalltype dllregisterserver () {char szmodule [1024]; DWORD dwresult =: getmodulefil Ename (hmodule) g_hmodule, szmodule, 1024); If (dwresult = 0) Return-1; return registerserver (clsid_string, szmodule, "string. object "," mycom string component ", null);} extern" C "hresult stdmethodcalltype dllunregisterserver () {return unregisterserver (clsid_string," string. object ", null);} extern" C "hresult stdmethodcalltype dllgetclassobject (_ in refclsid rclsid, _ in refiid riid, _ deref_out lpvoid far * GMM) {If (rclsid = clsid_string) {cfactory * pfactory = new cfactory (); If (pfactory = NULL) return e_outofmemory; hresult hR = pfactory-> QueryInterface (riid, 1); Return hr;} else {return class_e_classnotavailable;} hresult string: QueryInterface (refiid IID, lpvoid * bp) {If (IID = iid_iunknown) {* GMM = (iunknown *) This; (iunknown *) (* bp))-> addref ();} else if (IID = iid_istring) {* GMM = (iclassfactory *) This; (Iclassfactory *) (* GMM)-> addref ();} else {* NPV = NULL; return e_nointerface;} return s_ OK;} string: string () {m_ref = 0;} string ::~ String () {} ulong string: addref () {m_ref ++; return m_ref;} ulong string: release () {m_ref --; If (m_ref = 0) {Delete this; return 0;} return m_ref;} hresult string: getstring (char * chbuf, long clength) {long I; // copy the buffer of iexample to the input buffer. I = lstrlen (buffer); -- clength; if (I> clength) I = clength; copymemory (chbuf, buffer, I ); chbuf [I] = 0; Return (0);} hresult string: setstring (char * chbuf) {dword I; // Copy the passed STR to the buffer of iexample. I = lstrlen (chbuf); if (I> 79) I = 79; copymemory (buffer, chbuf, I ); buffer [I] = 0; Return (0);} hresult string: aboutmessage () {MessageBox (null, "Hello, I am a message box! "," Message ", mb_ OK); Return s_ OK ;}

9. Write the test file (remember to manually register the DLL)

#include "IString.h"#include <Windows.h>#include <iostream>using namespace std;// {913AAE18-1D57-4868-AF2F-B47D32163E8F}extern "C" const GUID CLSID_String = { 0x913aae18, 0x1d57, 0x4868, { 0xaf, 0x2f, 0xb4, 0x7d, 0x32, 0x16, 0x3e, 0x8f } };// {416DC65F-48E2-436a-BA34-FC00AC3DA598}extern "C" const GUID IID_IString = { 0x416dc65f, 0x48e2, 0x436a, { 0xba, 0x34, 0xfc, 0x0, 0xac, 0x3d, 0xa5, 0x98 } };int main(){IString *pIStr;IUnknown *pIUk = NULL;HRESULT hr;char chGetChar[80];CLSID rclsid;if(CoInitialize(NULL) != S_OK){cout<<"initialize Failed"<<endl;return -1;}hr = CLSIDFromProgID(OLESTR("STRING.Object"),&rclsid);if (hr != S_OK){cout<<"Can't find the dictionary CLSID!"<<endl;return -2;}hr = CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(LPVOID*)&pIUk);if (hr != S_OK){cout<<"Create object failed!"<<endl;return -2;}hr = pIUk->QueryInterface(IID_IString,(LPVOID*)&pIStr);if (hr != S_OK) {pIUk->Release();printf("QueryInterface IString failed!\n");return -3;}pIStr->SetString("wqlgregergerg");pIStr->GetString(chGetChar,sizeof(chGetChar));cout<<chGetChar<<endl;pIStr->AboutMessage();CoUninitialize();return 0;}

Finally, the post is complete. A complete example! Learn together.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.