安全中国首页 > 文章中心 > 编释语言
 
安全中国网友投稿专用上传FTP空间:
Ftp服务器:download.anqn.com
Ftp端口:21
用户名:anqn
密 码:anqn.com
 

《加密解密 技术内幕》 COM 原理与应用

更新时间:2008-4-3 0:19:42
责任编辑:流火
热 点:


(savetime 注:下面代码中 ppv 指针的应用,好像应该是 void **)

 

  HRESULT CoCreateInstance(const CLSID& clsid, IUnknown *pUnknownOuter,

    DWORD dwClsContext, const IID& iid, void *ppv)

  {

    IClassFactory *pCF;

    HRESULT hr;

 

    hr = CoGetClassObject(clsid, dwClsContext, NULL, IID_IClassFactory,

         (void *) pCF);

    if (FAILED(hr)) return hr;

    hr = pCF->CreateInstance(pUnknownOuter, iid, (void *)ppv);

    pFC->Release();

    return hr;

  }

 

从这段代码我们可以看出,CoCreateInstance 函数首先利用 CoGetClassObject 函数创建类厂对象,然后用得到的类厂对象的接口指针创建真正的 COM 对象,最后把类厂对象释放掉并返回,这样就把类厂屏蔽起来。

 

但是,用 CoCreateInstance 并不能创建远程机器上的对象,因为在调用 CoGetClassObject 时,把第三个用于指定服务器信息的参数设置为 NULL。如果要创建远程对象,可以使用 CoCreateInstance 的扩展函数 CoCreateInstanceEx:

 

  HRESULT CoCreateInstanceEx(const CLSID& clsid, IUnknown *pUnknownOuter,

    DWORD dwClsContext, COSERVERINFO *pServerInfo, DWORD dwCount,

    MULTI_QI *rgMultiQI);

 

前三个参数与  CoCreateInstance 一样,pServerInfo 与 CoGetClassOjbect 的参数一样,用于指定服务器信息,最后两个参数 dwCount 和 rgMultiQI 指定了一个结构数组,可以用于保存多个对象接口指针,其目的在于一次获得多个接口指针,以便减少客户程序与组件程序之间的频繁交互,这对于网络环境下的远程对象是很有意义的。

 

-------------------------------------------------------------------------------

   COM 库的初始化

-------------------------------------------------------------------------------

调用 COM 库的函数之前,为了使函数有效,必须调用 COM 库的初始化函数:

 

  HRESULT CoInitialize(IMalloc *pMalloc);

 

pMalloc 用于指定一个内存分配器,可由应用程序指定内存分配原则。一般情况下,我们直接把参数设为 NULL,则 COM 库将使用缺省提供的内存分配器。

 

返回值:S_OK         表示初始化成功

        S_FALSE      表示初始化成功,但这次调用不是本进程中首次调用初始化函数

        S_UNEXPECTED 表示初始化过程中发生了错误,应用程序不能使用 COM 库

 

通常,一个进程对 COM 库只进行一次初始化,而且,在同一个模块单元中对 COM 库进行多次初始化并没有意义。唯一不需要初始化 COM 库的函数是获取 COM 库版本的函数:

 

  DWORD CoBuildVersion();

 

返回值:高 16 位  主版本号

        低 16 位  次版本号

 

COM 程序在用完 COM 库服务之后,通常是在程序退出之前,一定要调用终止 COM 库服务函数,以便释放 COM 库所维护的资源:

 

  void CoUninitialize(void);

 

注意:凡是调用 CoInitialize 函数返回 S_OK 的进程或程序模块一定要有对应的 CoUninitialize 函数调用,以保证 COM 库有效地利用资源。

(? 如果在一个模块中调用 CoInitialize 返回 S_OK,那么它调用 CoUnitialize 函数后,其它也在使用 COM 库的模块是否会出错误?还是 COM 库会自动检查有哪些模块在使用?)

 

-------------------------------------------------------------------------------

   COM 库的内存管理

-------------------------------------------------------------------------------

由于 COM 组件程序和客户程序是通过二进制级标准建立连接的,所以在 COM 应用程序中凡是涉及客户、COM 库和组件三者之间内存交互(分配和释放不在同一个模块中)的操作必须使用一致的内存管理器。COM 提供的内存管理标准,实际上是一个 IMalloc 接口:

 

  // IID_IMalloc: {00000002-0000-0000-C000-000000000046}

  class IMalloc: public IUnknown

  {

    void * Alloc(ULONG cb) = 0;

    void * Realloc(void *pv, ULONG cb) = 0;

    void   Free(void *pv) = 0;

    ULONG  GetSize(void *pv) = 0;   // 返回分配的内存大小

    int    DidAlloc(void *pv) = 0;  // 确定内存指针是否由该内存管理器分配

    void   HeapMinimize() = 0;      // 使堆内存尽可能减少,把没用到的内存还给

                                    // 操作系统,用于性能优化

  }

 

获得 IMalloc 接口指针:

 

  HRESULT CoGetMalloc(DWORD dwMemContext, IMalloc **ppMalloc);

 

CoGetMalloc 函数的第一个参数 dwMemContext 用于指定内存管理器的类型。COM 库中包含两种内存管理器,一种就是在初始化时指定的内存管理器或者其内部缺省的管理器,也称为作业管理器(task allocator),这种管理器在本进程内有效,要获取该管理器,在 dwMemContext 参数中指定为 MEMCTX_TASK;另一种是跨进程的共享分配器,由 OLE 系统提供,要获取这种管理器,dwMemContext 参数中指定为 MEMCTX_SHARED,使用共享管理器的便利是,可以在一个进程内分配内存并传给第二个进程,在第二个进程内使用此内存甚至释放掉此内存。

 

只要函数的返回值为 S_OK,则 ppMalloc 就指向了 COM 库的内存管理器接口指针,可以使用它进行内存操作,使用完毕后,应该调用 Release 成员函数释放控制权。

 

COM 库封装了三个 API 函数,可用于内存分配和释放:

 

  void * CoTaskMemAlloc(ULONG cb);

  void   CoTaskFree(void *pv);

  void   CoTaskMemRealloc(void *pv, ULONG cb);

 

这三个函数分配对应于 IMalloc 的三个成员函数:Alloc、Realloc 和 Free。

 

例:COM 程序如何从 CLSID 值找到相应的 ProgID 值:

 

  WCHAR *pwProgID;

  char   pszProgID[128];

  hResult = ::ProgIDFromCLSID(CLSID_Dictionary, &pwProgID);

  if (hResult != S_OK) {

    ...

  }

  wcstombs(pszProgID, pwProgID, 128);

  CoTaskMemFree(pwProgID);      // 注意:必须释放内存

 

在调用 COM 函数 ProgIDFromCLSID 返回之后,因为 COM 库为输出变量 pwProgID 分配了内存空间,所以应用程序在用完 pwProgID 变量之后,一定要调用 CoTaskMemFree 函数释放内存。该例子说明了在 COM 库中分配内存,而在调用程序中释放内存的一种情况。COM 库中其他一些函数也有类似的特性,尤其是一些包含不定长度输出参数的函数。

上一页 1 2 3 4 5 6 下一页

 
相关文章
一日一文章
 
一日一软件
一日一动画