COM初探(三)

COM初探(三)

(一)目标
COM初探(一)和(二)中实现的并非真正的COM程序。但是,前两步都是深入学习COM所必须经历的过程。本篇将实现一个完全的COM程序。此程序使用CoCreateInstance来获得COM对象的接口。

(二)定义接口ITimeBeijing
import "oaidl.idl";
import "ocidl.idl";

[
 uuid(AA4F6A70-E521-4d46-9F4B-BC23424CEA5B),
 object,
 pointer_default(unique)
]
interface ITimeBeijing : IUnknown
{
 HRESULT GetTimeBeijing([out]int* hour, [out]int* min, [out]int* sec);
};

[
 uuid(1DC3957D-B808-4e5c-B360-1DAE5B3EBED4),
 version(1.0),
]
library TimeBeijingLib
{
 importlib("stdole32.tlb");
 importlib("stdole2.tlb");

 [
  uuid(FB492283-0A76-400d-879F-5B70FBF0A493),
 ]
 coclass TimeBeijingClass
 {
  [default] interface ITimeBeijing;
 };
};

(三)定义和实现COM类TimeBeijingClass
// TimeBeijingClass.h: interface for the TimeBeijingClass class.
//
//

#if !defined(AFX_TIMEBEIJINGCLASS_H__E9D2F0AF_8EBB_438B_A2BC_6206DDAB91B6__INCLUDED_)
#define AFX_TIMEBEIJINGCLASS_H__E9D2F0AF_8EBB_438B_A2BC_6206DDAB91B6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "TimeBeijing.h"

class TimeBeijingClass : public ITimeBeijing 
{
public:
 TimeBeijingClass();
 ~TimeBeijingClass();

private:
 ULONG m_cRef;

public:
 //IUnknown Interface
 STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
 STDMETHOD_(ULONG, AddRef)();
 STDMETHOD_(ULONG, Release)();

 //ITimeBeijing Interface
 STDMETHOD(GetTimeBeijing)(int * hour, int* min, int * sec);
};

#endif // !defined(AFX_TIMEBEIJINGCLASS_H__E9D2F0AF_8EBB_438B_A2BC_6206DDAB91B6__INCLUDED_)

// TimeBeijingClass.cpp: implementation of the TimeBeijingClass class.
//
//

#include "TimeBeijingClass.h"
#include "time.h"
#include "stdio.h"
#include "TimeBeijing_i.c"
//
// Construction/Destruction
//

TimeBeijingClass::TimeBeijingClass()
{
 printf("TimeBeijingClass - constructor/n");
 m_cRef = 0;
}

TimeBeijingClass::~TimeBeijingClass()
{
 printf("TimeBeijingClass - destructor/n");
}

STDMETHODIMP TimeBeijingClass::QueryInterface(REFIID riid, void **ppv)
{
 printf("TimeBeijingClass - QueryInterface/n");
 if(riid == IID_ITimeBeijing)
  *ppv = static_cast<ITimeBeijing *>(this);
 else if(riid == IID_IUnknown)
  *ppv = static_cast<ITimeBeijing *>(this);
 else {
  *ppv = 0;
  return E_NOINTERFACE;
 }
 
 reinterpret_cast<IUnknown *>(*ppv)->AddRef();
 return S_OK;
}

STDMETHODIMP_(ULONG) TimeBeijingClass::AddRef()
{
 printf("TimeBeijingClass - AddRef/n");
 return ++m_cRef;
}

STDMETHODIMP_(ULONG) TimeBeijingClass::Release()
{
 printf("TimeBeijingClass - Release/n");
 ULONG res = --m_cRef; 
 if(res == 0)
  delete this;
 return res;
}

STDMETHODIMP TimeBeijingClass::GetTimeBeijing(int * hour, int* min, int * sec)
{
 printf("TimeBeijingClass - GetTimeBeijing/n");
 
 time_t ltime;
 struct tm *today;
 
 time(&ltime);
 today = localtime(&ltime);
 
 *hour = today->tm_hour;
 *min = today->tm_min;
 *sec = today->tm_sec;
 
 return S_OK;
}

(四)定义和实现类工厂TimeBeijingClassFactory
// TimeBeijingClassFactory.h: interface for the TimeBeijingClassFactory class.
//
//

#if !defined(AFX_TIMEBEIJINGCLASSFACTORY_H__AB2637DD_45D2_48CD_BAD8_46E372268A8C__INCLUDED_)
#define AFX_TIMEBEIJINGCLASSFACTORY_H__AB2637DD_45D2_48CD_BAD8_46E372268A8C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <unknwn.h>

class TimeBeijingClassFactory : public IClassFactory 
{
public:
 TimeBeijingClassFactory();
 ~TimeBeijingClassFactory();

public:
 //IUnknow Method
 STDMETHODIMP QueryInterface(REFIID,void**);
 STDMETHODIMP_(ULONG) AddRef();
 STDMETHODIMP_(ULONG) Release();
 
 //IClassFactory Method
 STDMETHODIMP CreateInstance(IUnknown * ,REFIID ,void **);
 STDMETHODIMP LockServer(BOOL fLock);
 
private:
 LONG m_cRef;

};

#endif // !defined(AFX_TIMEBEIJINGCLASSFACTORY_H__AB2637DD_45D2_48CD_BAD8_46E372268A8C__INCLUDED_)

// TimeBeijingClassFactory.cpp: implementation of the TimeBeijingClassFactory class.
//
//

#include "TimeBeijingClassFactory.h"
#include "stdio.h"
#include "TimeBeijingClass.h"
//
// Construction/Destruction
//

extern LONG g_cObjectAndLocks;

TimeBeijingClassFactory::TimeBeijingClassFactory()
{
 printf("TimeBeijingClassFactory - constructor/n");
 m_cRef = 0;
}

TimeBeijingClassFactory::~TimeBeijingClassFactory()
{
 printf("TimeBeijingClassFactory - destructor/n");
}

STDMETHODIMP_(ULONG) TimeBeijingClassFactory::AddRef(void)
{
 printf("TimeBeijingClassFactory - AddRef/n");
 return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) TimeBeijingClassFactory::Release(void)
{
 printf("TimeBeijingClassFactory - Release/n");
 return ::InterlockedDecrement(&m_cRef);
}

STDMETHODIMP TimeBeijingClassFactory::QueryInterface(REFIID riid,void ** ppv)
{
 printf("TimeBeijingClassFactory - QueryInterface/n");

 *ppv = NULL;
 if(riid == IID_IUnknown || riid == IID_IClassFactory)
 {
  *ppv = static_cast<IClassFactory *>(this);
  reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  return S_OK;
 }
 else
  return (*ppv=0),E_NOINTERFACE;
}

STDMETHODIMP TimeBeijingClassFactory::CreateInstance(IUnknown * pUnkOuter,REFIID riid,void ** ppv)
{
 printf("TimeBeijingClassFactory - CreateInstance/n");

 *ppv=NULL;
 
 if(pUnkOuter != NULL)
  return CLASS_E_NOAGGREGATION;
 
 TimeBeijingClass * pTimeBeijingClass = new TimeBeijingClass;
 if(pTimeBeijingClass == NULL)
  return E_OUTOFMEMORY;
 
 HRESULT hr = pTimeBeijingClass->QueryInterface(riid,ppv);
 
 if(FAILED(hr))
  delete pTimeBeijingClass;
 
 return hr;
 
}

STDMETHODIMP TimeBeijingClassFactory::LockServer(BOOL fLock)
{
 printf("TimeBeijingClassFactory - LockServer/n");
 if(fLock)
  ::InterlockedIncrement(&g_cObjectAndLocks);
 else
  ::InterlockedDecrement(&g_cObjectAndLocks);
 return NOERROR;
 
}

(五)DLL服务器主文件
#include <windows.h>
#include <objbase.h>
#include <initguid.h>
#include "TimeBeijingClassFactory.h"
#include "TimeBeijing_i.c"

LONG g_cObjectAndLocks=0;

const char * g_RegTable[][3]={
 {"CLSID//{FB492283-0A76-400d-879F-5B70FBF0A493}",
  0,
  "TimeBeijing"},

 {"CLSID//{FB492283-0A76-400d-879F-5B70FBF0A493}//InprocServer32",
 0,
 (const char * )-1},

 {"CLSID//{FB492283-0A76-400d-879F-5B70FBF0A493}//ProgID",
 0,
 "Justin.TimeBeijing.2"},

 {"Justin.TimeBeijing.2",
 0,
 "TimeBeijing"},

 {"Justin.TimeBeijing.2//CLSID",
 0,
 "{FB492283-0A76-400d-879F-5B70FBF0A493}"},
};

HINSTANCE  g_hinstDll;

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 g_hinstDll = (HINSTANCE)hModule;
    return TRUE;
}

STDAPI DllUnregisterServer(void)//从注册表中注销
{
 HRESULT hr = S_OK;
 char szFileName [MAX_PATH];
 ::GetModuleFileName(g_hinstDll,szFileName,MAX_PATH);
 
 int nEntries = sizeof(g_RegTable) / sizeof(*g_RegTable);
 
 for(int i = 0; SUCCEEDED(hr) && i < nEntries; i ++)
 {
  const char * pszKeyName = g_RegTable[i][0];
  long err = ::RegDeleteKey(HKEY_CLASSES_ROOT, pszKeyName);
  if( err != ERROR_SUCCESS)
   hr = S_FALSE;
 }
 
 return hr;
}


STDAPI DllRegisterServer(void)//注册服务器
{
 HRESULT hr = S_OK;
 char szFileName [MAX_PATH];
 ::GetModuleFileName(g_hinstDll, szFileName, MAX_PATH);
 
 int nEntries = sizeof(g_RegTable) / sizeof(*g_RegTable);
 for(int i = 0 ; SUCCEEDED(hr) && i < nEntries; i ++)
 {
  const char * pszKeyName = g_RegTable[i][0];
  const char * pszValueName = g_RegTable[i][1];
  const char * pszValue = g_RegTable[i][2];
  
  if(pszValue == (const char *) - 1)
  {
   pszValue = szFileName;
  }
  
  HKEY hkey;
  long err = ::RegCreateKey(HKEY_CLASSES_ROOT, pszKeyName, &hkey);
  if(err == ERROR_SUCCESS)
  {
   err = ::RegSetValueEx( hkey,
    pszValueName,
    0,
    REG_SZ,
    ( const BYTE*)pszValue,
    ( strlen(pszValue)+1 ) );
   ::RegCloseKey(hkey);
  }
  if( err != ERROR_SUCCESS)
  {
   ::DllUnregisterServer();
   hr = E_FAIL;
  }
  
 }
 return hr;
}
      
STDAPI DllGetClassObject(REFCLSID rclsid ,REFIID riid,void **ppv)
{
 if(rclsid == CLSID_TimeBeijingClass)
 {
  TimeBeijingClassFactory *pFactory = new TimeBeijingClassFactory;

  if(pFactory == NULL)
   return E_OUTOFMEMORY;

  HRESULT hr = pFactory->QueryInterface(riid, ppv);
  return hr;
 }
 
 return CLASS_E_CLASSNOTAVAILABLE;
}

STDAPI DllCanUnloadNow(void)
{
 return ( g_cObjectAndLocks == 0 )
  ? S_OK : E_FAIL;
}

(六)DEF文件
LIBRARY      "TimeBeijing.DLL"

EXPORTS
 DllCanUnloadNow     @1 PRIVATE
 DllGetClassObject   @2 PRIVATE
 DllRegisterServer   @3 PRIVATE
 DllUnregisterServer @4 PRIVATE

(七)测试程序
#include "../TimeBeijing.h"
#include "../TimeBeijing_i.c"

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 HRESULT hr = CoInitialize(0);//初始化COM

 int h, m, s;

 ITimeBeijing * pTimeBeijing = NULL;

 hr = ::CoCreateInstance(CLSID_TimeBeijingClass, //获取接口指针
  NULL,
  CLSCTX_INPROC,
  IID_ITimeBeijing,
  (void**)&pTimeBeijing);
  
 if(SUCCEEDED(hr))
 {
  pTimeBeijing->GetTimeBeijing(&h, &m, &s);//调用接口
  printf("当前时间:%d : %d : %d/n", h, m, s);
 }
 
 pTimeBeijing->Release();//释放接口

 CoUninitialize();
  
 system("pause");

 return 0;
}

(八)测试结果
在命令行下输入:regsvr32 TimeBeijing.dll 启动服务器。

执行测试程序,结果如下:
TimeBeijingClassFactory - constructor
TimeBeijingClassFactory - QueryInterface
TimeBeijingClassFactory - AddRef
TimeBeijingClassFactory - CreateInstance
TimeBeijingClass - constructor
TimeBeijingClass - QueryInterface
TimeBeijingClass - AddRef
TimeBeijingClass - AddRef
TimeBeijingClass - Release
TimeBeijingClassFactory - Release
TimeBeijingClass - QueryInterface
TimeBeijingClass - AddRef
TimeBeijingClass - Release
TimeBeijingClass - GetTimeBeijing
当前时间:15 : 27 : 42
TimeBeijingClass - Release
TimeBeijingClass - destructor
请按任意键继续 . . .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值