分享

com技术内幕

 uqt123 2012-07-25

com技术内幕--读书笔记(7)

分类: com 66人阅读 评论(0) 收藏 举报

第7章

相信有了前六章的知识积累,学些以后的章节将会很顺利。本章实现了一个真正的COM组件,并通过client客户端来使用这个组件。

本章将介绍类厂,类厂是能够创建其他组件的组件,CoCreateInstance函数也是按照一定方法通过类厂来创建组件的。

CoCreateInstance

CoCreateInstance函数是COM库的函数,函数原型如下

  1. HRESULT __stdcall CoCreateInstance(const CLSID &clsid,   
  2.                            IUnknown *pIUnkownOuter, //Outer Component   
  3.                                DWORD dwClsContext,      //Server Context   
  4.                                    const IID &iid,  
  5.                            void **ppv);  

其中前四个是输入参数,最后一个是输出参数。第一个参数clsid是所创建组件的CLSID,第二个参数pIUnkownOuter是聚合组件需要用的,将在第8章介绍,第三个参数dwClsContext是限定所创建组件的执行上下文,第四个参数iid是所创建组件的接口的IID,第五个参数ppv将返回该接口的指针。

dwClsContext

dwClsContext可以控制所创建是与客户在相同的进程中运行,还是在不同的进程中运行,或者是在另外一台机器上运行。此参数可以是如下值的组合

CLSCTX_INPROC_SERVER         客户希望创建在同一进程中运行的组件,因此组件必须是在DLL中实现。

CLSCTX_INPROC_HANDLER      客户希望创建进程中处理器。

CLSCTX_LOCAL_SERVER           客户希望创建一个在同一机器上的另外一个进程中运行的组件。组件是由EXE实现的。

CLSCTX_REMOTE_SERVER       客户希望创建一个在远程机器上运行的组件。分布式COM组件。

在OBJBASE.H中定义了一些上述值的组合。


CoCreateInstance的具有一定的不灵活性,解决问题的办法是使用专门用于创建所需组件的组件,这个组件就是类厂。

类厂

某个特定的类厂可以创建某个特定CLSID相对应的组件,客户可以通过类厂提供的接口来对组件的创建过程进行控制。客户使用CoCreateInstance所创建的组件实际上是通过类厂的IClassFactory创建的,使用类厂创建组件的步骤是首先创建类厂,然后使用IClassFactory创建所需的组件。

创建类厂

COM库函数CoGetClassObject创建同某个CLSID相应的类厂。函数原型如下

  1. HRESULT __stdcall CoGetClassObject(const CLSID &clsid,  
  2.                            DWORD dwClsContext,  
  3.                                    COSERVERINFO *pServerInfo,  
  4.                                    const IID &iid,  
  5.                                    void **ppv);  

同CoCreateInstance非常相似。第一个参数const CLSID&待创建组件的CLSID,第二个参数DWORD dwClsContext是待创建组件的执行上下文,第三个参数COSERVERINFO*用于远程组件的访问,将在第10章讨论,第四个参数const IID&是IClassFactory接口的IID,第五个参数返回IClassFactory接口的指针。

创建组件

IClassFactory

大多数组件是使用IClassFactory来创建的,原型如下

  1. interface IClassFactory:IUnknown  
  2. {  
  3.     HRESULT __stdcall CreateInstance(IUnkown *pUnknownOuter, const IID &id, void **ppv);  
  4.     HRESULT __stdcall LockServer(BOOL bLock);  
  5. };  

IClassFactory::CreateInstance函数的第一个参数IUnknown*是组件聚合使用的,将在第8章介绍,后两个参数跟CoCreateInstance后两个参数作用相同,将在创建组件的

同时返回此组件的某个接口指针。可以看到IClassFactory::CreateInstance并没有接收一个CLSID参数,这意味着此函数将只能创建同某个CLSID——即传给CoGetClassObject的参数CLSID相应的组件。

在两种情况下使用创建类厂再创建组件的方法,而不是直接使用CoCreateInstance的方法直接创建组件

(1)想使用IClassFactory2来创建组件。IClassFactory2是Microsoft定义的另外一个接口,此接口在IClassFactory的基础上增加了获取组件接口的许可权限功能。

(2)需要创建一个组件的多个实例。这样只需创建相应的类厂一次,而CoCreateInstance需要为每一个组件实例分别创建并释放相应的类厂。

类厂的特性

(1)类厂将只能给你创建同某个CLSID相应的组件。

(2)与某个特定CLSID相应的类厂是由组件开发人员来实现的。大多数情况下,类厂组件包含在它所创建的组件的相同的DLL中。

类厂的创建

客户通过CoGetClassObject来创建类厂,这就需要在DLL中实现一个特定的函数,此函数名为DllGetClassObject,函数原型如下

  1. STDAPI DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv);  
函数的三个参数同CoGetClassObject中参数的意义相同。

通过类厂来创建组件的示意图如下,COM库函数CoGetClassObject将根据传入参数CLSID查询注册表,装载组件所在的DLL库。

CFactory只不过是另外一个组件而已,它也跟其他组件一样实现了IUnknown接口。

IClassFactory::CreateInstance和DllGetClassObject的实现是相同的,这两个函数都将创建一个组件然后向它查询某个接口。


组件的注册

实现组件的DLL中输出四个函数,除了DllGetClassObject外,DllRegisterServer和DllUnregisterServer将用于组件在注册表中注册和取消注册(链接的时候需要链接Advapi32.lib),调用regsvr32来完成注册和取消。

类厂的复用

在设计类厂和组件的时候,可以做到只用一个类厂的实现来完成所有组件的创建。将在第9章中实现。但即使是这样,类厂CFactory的一个实例也仅能创建一个同某个CLSID相应的组件。


DLL的卸载

COM库中实现了一个CoFreeUnusedLibraries的函数,以释放那些不再需要使用的DLL库所占用的内存,由组件的客户进行调用。

DllCanUnloadNow函数

也是在实现组件的DLL中的输出函数,CoFreeUnusedLibraries函数将调用DllCanUnloadNow函数,以询问Dll是否可以被卸载。代码中g_lComponents的作用就是这个,可以看到IClassFactory::CreateInstance也就是说在创建组件的时候,组件的构造函数都可以将g_lComponents增大,组件的析构函数可以将g_lComponents的值减小。若g_lComponets值为0,CoFreeUnusedLibraries可以将组件的DLL卸载掉。

LockServer函数

使用g_lComponents只是对DLL中的组件进行了记数,另外一个组件CFactory并没有记数。对类厂的记数使用了IFactory::LockServer函数,组件Server内部设置了另外一个与g_IComponents不同的计数值进行计数。(将在第10章进行讨论,主要原因是因为第10章将会讲到的进程外组件(exe实现的)的类厂无法像进程中的组件(dll实现的)一样方便的进行记数。)


本章代码

组件端:

cmpnt.cpp

  1. //   
  2. //cmpnt.cpp   
  3. //use: cl /LD cmpnt.cpp guids.cpp registry.cpp cmpnt.def uuid.lib ole32.lib Advapi32.lib    
  4. //     regsvr32 -s cmpnt.dll   
  5.   
  6. #include <objbase.h>   
  7. #include "iface.h"    //interface declarations   
  8. #include "Registry.h"  //Registry helper function   
  9. #include <iostream>   
  10. #include <string>   
  11. using namespace std;  
  12.   
  13. //trace function   
  14. void trace(string msg)  
  15. {  
  16.     cout<<msg<<endl;  
  17. }   
  18.   
  19. //global variable   
  20. //   
  21. static HMODULE g_hModule = NULL;        //DLL Module handle   
  22. static long    g_lComponent = 0;        //Count of active component   
  23. static long    g_lServerLocks = 0;      //Count of locks   
  24.   
  25. //Friendly name of component   
  26. const char g_szFriendlyName[] = "InsideCOM Chapter 7 Example";  
  27.   
  28. //Version independent ProgID   
  29. const char g_szVerIndProgID[] = "InsideCOM.Chap07";  
  30.   
  31. //ProgID   
  32. const char g_szProgID[] = "InsideCOM.Chap07.1";  
  33.   
  34. //Component   
  35. class CA:public IX, public IY  
  36. {  
  37. public:  
  38.     //IUnknown   
  39.     virtual HRESULT __stdcall QueryInterface(const IID &iid, void **ppv);  
  40.     virtual ULONG   __stdcall AddRef();  
  41.     virtual ULONG   __stdcall Release();  
  42.     virtual void    __stdcall Fx() {cout<<"Fx"<<endl;}  
  43.     virtual void    __stdcall Fy() {cout<<"Fy"<<endl;}  
  44.     CA();  
  45.     ~CA();  
  46. protected:  
  47.     long m_cRef;  
  48. };  
  49.   
  50. CA::CA()  
  51. {  
  52.     m_cRef = 1;   //注意这里与前几章不一样,m_cRef=1意味着只要CA组件被创建就计数为1,这样IFactory::CreateInstance创建CA组   
  53.                   //件时,就不用调用AddRef()了   
  54.     InterlockedIncrement(&g_lComponent);  
  55. }  
  56.   
  57. CA::~CA()  
  58. {  
  59.     InterlockedDecrement(&g_lComponent);  
  60.     trace("Component:destroy self");  
  61. }  
  62.   
  63. //IUnknown implement   
  64. HRESULT __stdcall CA::QueryInterface(const IID &iid, void **ppv)  
  65. {  
  66.     if(iid == IID_IUnknown)  
  67.     {  
  68.         *ppv = static_cast<IX*>(this);  
  69.     }  
  70.     else if(iid == IID_IX)  
  71.     {  
  72.         *ppv = static_cast<IX*>(this);  
  73.         trace("component: return pointer to ix");  
  74.     }  
  75.     else if(iid == IID_IY)  
  76.     {  
  77.         *ppv = static_cast<IY*>(this);  
  78.         trace("component: return pointer to iy");  
  79.     }  
  80.     else  
  81.     {  
  82.         *ppv = NULL;  
  83.         return E_NOINTERFACE;  
  84.     }  
  85.     reinterpret_cast<IUnknown*>(*ppv)->AddRef();  
  86.     return S_OK;  
  87. }  
  88.   
  89. ULONG __stdcall CA::AddRef()  
  90. {  
  91.     return InterlockedIncrement(&m_cRef);  
  92. }  
  93.   
  94. ULONG __stdcall CA::Release()  
  95. {  
  96.     if(InterlockedDecrement(&m_cRef)== 0)  
  97.     {  
  98.         delete this;  
  99.         return 0;  
  100.     }  
  101.     return m_cRef;  
  102. }  
  103.   
  104. ///////////////////////////////////////////   
  105. //class factory   
  106. //   
  107. class CFactory:public IClassFactory  
  108. {  
  109. public:  
  110.     //iunknown   
  111.     virtual HRESULT __stdcall QueryInterface(const IID &iid, void **ppv);  
  112.     virtual ULONG   __stdcall AddRef();  
  113.     virtual ULONG   __stdcall Release();  
  114.     //interface IClassFactory   
  115.     virtual HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter, const IID &iid, void **ppv);  
  116.     virtual HRESULT __stdcall LockServer(BOOL bLock);  
  117.     //constructor   
  118.     CFactory():m_cRef(1){}  
  119.     //destructor   
  120.     ~CFactory()  
  121.     {  
  122.         trace("class factory :destory self");  
  123.     }  
  124. private:  
  125.     long m_cRef;  
  126. };  
  127.   
  128. //   
  129. //class factory IUnknown implementation   
  130. //   
  131. HRESULT __stdcall CFactory::QueryInterface(const IID &iid, void **ppv)  
  132. {  
  133.     if((iid == IID_IUnknown) || (iid == IID_IClassFactory))  
  134.     {  
  135.         *ppv = static_cast<IClassFactory*>(this);  
  136.     }  
  137.     else  
  138.     {  
  139.         *ppv = NULL;  
  140.         return E_NOINTERFACE;  
  141.     }  
  142.     reinterpret_cast<IUnknown*>(*ppv)->AddRef();  
  143.     return S_OK;  
  144. }  
  145.   
  146. ULONG __stdcall CFactory::AddRef()  
  147. {  
  148.     return InterlockedIncrement(&m_cRef);  
  149. }  
  150.   
  151. ULONG __stdcall CFactory::Release()  
  152. {  
  153.     if(InterlockedDecrement(&m_cRef) == 0)  
  154.     {  
  155.         delete this;  
  156.         return 0;  
  157.     }  
  158.     return m_cRef;  
  159. }  
  160.   
  161. //   
  162. //IClassFactory implementation   
  163. //   
  164. HRESULT __stdcall CFactory::CreateInstance(IUnknown *pUnknownOuter, const IID &iid, void **ppv)  
  165. {  
  166.     trace("class factory : create component");  
  167.     //Can not aggregate   
  168.     if(pUnknownOuter != NULL)  
  169.     {  
  170.         return CLASS_E_NOAGGREGATION;  
  171.     }  
  172.     //create component   
  173.     CA *pA = new CA();  
  174.     if(pA == NULL)  
  175.     {  
  176.         return E_OUTOFMEMORY;  
  177.     }  
  178.     //Get requested interface   
  179.     HRESULT hr = pA->QueryInterface(iid, ppv);  
  180.   
  181.     //Release the IUnknown pointer   
  182.     pA->Release();  
  183.     return hr;  
  184. }  
  185.   
  186. //lock server   
  187. HRESULT __stdcall CFactory::LockServer(BOOL bLock)  
  188. {  
  189.     if(bLock)  
  190.     {  
  191.         InterlockedIncrement(&g_lServerLocks);  
  192.     }  
  193.     else  
  194.     {  
  195.         InterlockedDecrement(&g_lServerLocks);  
  196.     }  
  197.     return S_OK;  
  198. }  
  199.   
  200. /////////////////////////////////////////////   
  201. //export function   
  202. //   
  203. //get class factory   
  204. STDAPI DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv)  
  205. {  
  206.     trace("DllGetClassObeject: create class factory");  
  207.     if(clsid != CLSID_Component1)  
  208.     {  
  209.         return CLASS_E_CLASSNOTAVAILABLE;  
  210.     }  
  211.     //create class factory   
  212.     CFactory *pFactory = new CFactory;  
  213.     if(pFactory == NULL)  
  214.     {  
  215.         return E_OUTOFMEMORY;  
  216.     }  
  217.     HRESULT hr = pFactory->QueryInterface(iid, ppv);  
  218.     pFactory->Release();  
  219.     return hr;  
  220. }  
  221.   
  222. STDAPI DllCanUnloadNow()  
  223. {  
  224.     if((g_lComponent == 0) && (g_lServerLocks == 0))  
  225.     {  
  226.         return S_OK;  
  227.     }  
  228.     else  
  229.     {  
  230.         return S_FALSE;  
  231.     }  
  232. }  
  233.   
  234. //server registration   
  235. STDAPI DllRegisterServer()  
  236. {  
  237.     return RegisterServer(g_hModule,  
  238.                           CLSID_Component1,  
  239.                           g_szFriendlyName,  
  240.                           g_szVerIndProgID,  
  241.                           g_szProgID);  
  242. }  
  243.   
  244. //server unregistration   
  245. STDAPI DllUnregisterServer()  
  246. {  
  247.     return UnregisterServer(CLSID_Component1,  
  248.                             g_szVerIndProgID,  
  249.                             g_szProgID);  
  250. }  
  251.   
  252. BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, void *lpReserved)  
  253. {  
  254.     if(dwReason == DLL_PROCESS_ATTACH)  
  255.     {  
  256.         g_hModule = hModule;  
  257.     }  
  258.     return TRUE;  
  259. }  
  260.   
  261.    

cmpnt.def

  1. LIBRARY         Cmpnt.dll  
  2. DESCRIPTION     'Chapter 7 Example COM Component'  
  3.   
  4. EXPORTS         DllGetClassObject   @2  PRIVATE  
  5.                 DllRegisterServer   @3  PRIVATE  
  6.                 DllUnregisterServer @4  PRIVATE  
  7.                 DllCanUnloadNow     @5  PRIVATE  

registry.h

  1. #ifndef _REGISTRY_H_   
  2. #define _REGISTRY_H_   
  3.   
  4. HRESULT RegisterServer(HMODULE hModule,   
  5.                        const CLSID &clsid,  
  6.                        const char *szFriendlyName,  
  7.                        const char *szVerIndProgID,  
  8.                        const char *szProgID);  
  9. HRESULT UnregisterServer(const CLSID &clsid,  
  10.                          const char *szVerIndProgID,  
  11.                          const char *szProgID);  
  12. #endif  

registry.cpp

  1. //   
  2. //registry.cpp   
  3. //   
  4. #include <objbase.h>   
  5. #include <cassert>   
  6. #include "registry.h"   
  7.   
  8. //   
  9. //Internal functions    
  10.   
  11. //Set the key and its value   
  12. BOOL SetKeyAndValue(const char *szKey, const char *szSubKey, const char *szValue);  
  13.   
  14. //Convert a clsid to a char string   
  15. void CLSIDtochar(const CLSID &clsid, char *szClsID, int nLength);  
  16.   
  17. //Delete szKeyChild and all its child   
  18. LONG RecursiveDeleteKey(HKEY hKeyParent, const char *szKeyChild);  
  19.   
  20. const int CLSID_STRING_SIZE = 39 ;  
  21.   
  22. //   
  23. // Register the component in the registry.   
  24. //   
  25. HRESULT RegisterServer(HMODULE hModule,            // DLL module handle   
  26.                        const CLSID& clsid,         // Class ID   
  27.                        const char* szFriendlyName, // Friendly Name   
  28.                        const char* szVerIndProgID, // Programmatic   
  29.                        const char* szProgID)       //   IDs   
  30. {  
  31.     char szModule[512] ;  
  32.     DWORD dwResult =::GetModuleFileName(hModule, szModule, sizeof(szModule)/sizeof(char));  
  33.   
  34.     assert(dwResult != 0) ;  
  35.   
  36.     // Convert the CLSID into a char.   
  37.     char szCLSID[CLSID_STRING_SIZE] ;  
  38.     CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)) ;  
  39.   
  40.     // Build the key CLSID\\{...}   
  41.     char szKey[64] ;  
  42.     strcpy(szKey, "CLSID\\") ;  
  43.     strcat(szKey, szCLSID) ;  
  44.     
  45.     // Add the CLSID to the registry.   
  46.     SetKeyAndValue(szKey, NULL, szFriendlyName) ;  
  47.   
  48.     // Add the server filename subkey under the CLSID key.   
  49.     SetKeyAndValue(szKey, "InprocServer32", szModule) ;  
  50.   
  51.     // Add the ProgID subkey under the CLSID key.   
  52.     SetKeyAndValue(szKey, "ProgID", szProgID) ;  
  53.   
  54.     // Add the version-independent ProgID subkey under CLSID key.   
  55.     SetKeyAndValue(szKey, "VersionIndependentProgID",  
  56.                    szVerIndProgID) ;  
  57.   
  58.     // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.   
  59.     SetKeyAndValue(szVerIndProgID, NULL, szFriendlyName) ;   
  60.     SetKeyAndValue(szVerIndProgID, "CLSID", szCLSID) ;  
  61.     SetKeyAndValue(szVerIndProgID, "CurVer", szProgID) ;  
  62.   
  63.     // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.   
  64.     SetKeyAndValue(szProgID, NULL, szFriendlyName) ;   
  65.     SetKeyAndValue(szProgID, "CLSID", szCLSID) ;  
  66.   
  67.     return S_OK ;  
  68. }  
  69.   
  70. //   
  71. // Remove the component from the registry.   
  72. //   
  73. LONG UnregisterServer(const CLSID& clsid,         // Class ID   
  74.                       const char* szVerIndProgID, // Programmatic   
  75.                       const char* szProgID)       //   IDs   
  76. {  
  77.     // Convert the CLSID into a char.   
  78.     char szCLSID[CLSID_STRING_SIZE] ;  
  79.     CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)) ;  
  80.   
  81.     // Build the key CLSID\\{...}   
  82.     char szKey[64] ;  
  83.     strcpy(szKey, "CLSID\\") ;  
  84.     strcat(szKey, szCLSID) ;  
  85.   
  86.     // Delete the CLSID Key - CLSID\{...}   
  87.     LONG lResult = RecursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;  
  88.     assert( (lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND) ) ; // Subkey may not exist.   
  89.   
  90.     // Delete the version-independent ProgID Key.   
  91.     lResult = RecursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;  
  92.     assert((lResult == ERROR_SUCCESS) ||  
  93.            (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.   
  94.   
  95.     // Delete the ProgID key.   
  96.     lResult = RecursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID) ;  
  97.     assert((lResult == ERROR_SUCCESS) ||  
  98.            (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.   
  99.   
  100.     return S_OK ;  
  101. }  
  102.   
  103.   
  104. BOOL SetKeyAndValue(const char *szKey, const char *szSubKey, const char *szValue)  
  105. {  
  106.     HKEY hKey;  
  107.     char szKeyBuf[1024] ;  
  108.   
  109.     // Copy keyname into buffer.   
  110.     strcpy(szKeyBuf, szKey) ;  
  111.   
  112.     // Add subkey name to buffer.   
  113.     if (szSubKey != NULL)  
  114.     {  
  115.         strcat(szKeyBuf, "\\") ;  
  116.         strcat(szKeyBuf, szSubKey ) ;  
  117.     }  
  118.   
  119.     // Create and open key and subkey.   
  120.     long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,  
  121.                                   szKeyBuf,   
  122.                                   0, NULL, REG_OPTION_NON_VOLATILE,  
  123.                                   KEY_ALL_ACCESS, NULL,   
  124.                                   &hKey, NULL) ;  
  125.     if (lResult != ERROR_SUCCESS)  
  126.     {  
  127.         return FALSE ;  
  128.     }  
  129.   
  130.     // Set the Value.   
  131.     if (szValue != NULL)  
  132.     {  
  133.         RegSetValueEx(hKey, NULL, 0, REG_SZ,   
  134.                       (BYTE *)szValue,   
  135.                       strlen(szValue)+1) ;  
  136.     }  
  137.   
  138.     RegCloseKey(hKey) ;  
  139.     return TRUE ;  
  140.       
  141. }  
  142.   
  143.   
  144. LONG RecursiveDeleteKey(HKEY hKeyParent, const char *szKeyChild)  
  145. {  
  146.     // Open the child.   
  147.     HKEY hKeyChild ;  
  148.     LONG lRes = RegOpenKeyEx(hKeyParent, szKeyChild, 0,  
  149.                              KEY_ALL_ACCESS, &hKeyChild) ;  
  150.     if (lRes != ERROR_SUCCESS)  
  151.     {  
  152.         return lRes ;  
  153.     }  
  154.   
  155.     // Enumerate all of the decendents of this child.   
  156.     FILETIME time ;  
  157.     char szBuffer[256] ;  
  158.     DWORD dwSize = 256 ;  
  159.     while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,  
  160.                         NULL, NULL, &time) == S_OK)  
  161.     {  
  162.         // Delete the decendents of this child.   
  163.         lRes = RecursiveDeleteKey(hKeyChild, szBuffer) ;  
  164.         if (lRes != ERROR_SUCCESS)  
  165.         {  
  166.             // Cleanup before exiting.   
  167.             RegCloseKey(hKeyChild) ;  
  168.             return lRes;  
  169.         }  
  170.         dwSize = 256 ;  
  171.     }  
  172.   
  173.     // Close the child.   
  174.     RegCloseKey(hKeyChild) ;  
  175.   
  176.     // Delete this child.   
  177.     return RegDeleteKey(hKeyParent, szKeyChild) ;  
  178. }  
  179.   
  180. void CLSIDtochar(const CLSID &clsid, char *szClSID, int nLength)  
  181. {  
  182.     assert(nLength >= CLSID_STRING_SIZE) ;  
  183.     // Get CLSID   
  184.     LPOLESTR wszCLSID = NULL ;  
  185.     HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;  
  186.     assert(SUCCEEDED(hr)) ;  
  187.   
  188.     // Covert from wide characters to non-wide.   
  189.     wcstombs(szClSID, wszCLSID, nLength);  
  190.   
  191.     // Free memory.   
  192.     CoTaskMemFree(wszCLSID) ;  
  193. }  

iface.h

  1. //iface.h   
  2. //   
  3. #include <objbase.h>   
  4. interface IX:IUnknown  
  5. {  
  6.     virtual void __stdcall Fx() = 0;  
  7. };  
  8.   
  9. interface IY:IUnknown  
  10. {  
  11.     virtual void __stdcall Fy() = 0;  
  12. };  
  13.   
  14. interface IZ:IUnknown  
  15. {  
  16.     virtual void __stdcall Fz() = 0;  
  17. };  
  18.   
  19. extern const IID   IID_IX;  
  20. extern const IID   IID_IY;  
  21. extern const IID   IID_IZ;  
  22. extern const CLSID CLSID_Component1;  
  23.    

guids.cpp

  1. //   
  2. // GUIDs.cpp   
  3. //    
  4. #include <objbase.h>   
  5.   
  6. // {32bb8320-b41b-11cf-a6bb-0080c7b2d682}   
  7. extern const IID IID_IX =   
  8.     {0x32bb8320, 0xb41b, 0x11cf,  
  9.     {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;  
  10.   
  11. // {32bb8321-b41b-11cf-a6bb-0080c7b2d682}   
  12. extern const IID IID_IY =   
  13.     {0x32bb8321, 0xb41b, 0x11cf,  
  14.     {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;  
  15.   
  16. // {32bb8322-b41b-11cf-a6bb-0080c7b2d682}   
  17. extern const IID IID_IZ =   
  18.     {0x32bb8322, 0xb41b, 0x11cf,  
  19.     {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;  
  20.   
  21. // {0c092c21-882c-11cf-a6bb-0080c7b2d682}   
  22. extern const CLSID CLSID_Component1 =  
  23.     {0x0c092c21, 0x882c, 0x11cf,  
  24.     {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;  
  25.   
  26.    

客户端

clients.cpp

  1. //   
  2. //Client.cpp - client implementation   
  3. //use:cl client.cpp guids.cpp uuid.lib ole32.lib   
  4. //   
  5. #include <objbase.h>   
  6. #include "iface.h"   
  7. #include <iostream>   
  8. #include <string>   
  9. using namespace std;  
  10.   
  11. void trace(string msg)  
  12. {  
  13.     cout<<msg<<endl;  
  14. }  
  15.   
  16. int main(void)  
  17. {  
  18.     CoInitialize(NULL);  
  19.     trace("client:call CoCreateInstance to create component and get interface ix");  
  20.     IX *pIx = NULL;  
  21.     HRESULT hr = ::CoCreateInstance(CLSID_Component1, NULL, CLSCTX_INPROC_SERVER, IID_IX, (void**)&pIx);  
  22.     if(SUCCEEDED(hr))  
  23.     {  
  24.         trace("client:Succeeded getting IX");  
  25.         pIx->Fx();  
  26.         trace("client:Ask for interface IY");  
  27.         IY *pIy = NULL;  
  28.         hr = pIx->QueryInterface(IID_IY, (void**)&pIy);  
  29.         if(SUCCEEDED(hr))  
  30.         {  
  31.             trace("client:Succeeded getting IY");  
  32.             pIy->Fy();  
  33.             pIy->Release();  
  34.             trace("client:Release IY interface");  
  35.         }  
  36.         else  
  37.         {  
  38.             trace("client:Could not get interface IY");  
  39.         }  
  40.         trace("client:Ask for interface IZ");  
  41.         IZ *pIz = NULL;  
  42.         hr = pIx->QueryInterface(IID_IZ, (void**)&pIz);  
  43.         if(SUCCEEDED(hr))  
  44.         {  
  45.             trace("client:Succeeded getting IZ");  
  46.             pIz->Fz();  
  47.             pIz->Release();  
  48.             trace("client:Release IZ interface");  
  49.         }  
  50.         else  
  51.         {  
  52.             trace("client:Could not get interface IZ");  
  53.         }  
  54.         trace("client:Release IX interface");  
  55.         pIx->Release();  
  56.     }  
  57.     else  
  58.     {  
  59.         cout<<"Client: Could not create component.hr ="<<hex<<hr<<endl;  
  60.     }  
  61.     CoUninitialize();  
  62.     return 0;  
  63. }  


运行结果


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多