COM技术内幕--类厂

CoCreateInstance
在COM库中包含一个用于创建组件的名为CoCreateInstance函数。此函数要一个CLSID,参数,在些基础上创建相应组件的实例,并返回此组件实例的某个接口。
1) CoCreateInstance声明如下:
HRESULT __stdcall CoCreateInstance(
const CLSID& clsid,
IUnknown* pIUnknownOuter, // Out Component
DWORD dwClsCotext, // Server Context
const IID& iid,
void** ppv
)
2) CoCreateInstance的使用
HRESULT __stdcall CoCreateInstance(
const CLSID& clsid,
IUnknown* pIUnknownOuter, // Out Component
DWORD dwClsCotext, // Server Context
const IID& iid,
void** ppv
)
IX* pIX = NULL;
HRESULT hr = ::CoCreateInstance(CLSID_Component1, // 标识组件
NULL,
CLSCTX_INPROC_SERVER,
IID_IX, //表示希望得到的IX的指针
(void**)&pIX);
if (SUCCEEDED(hr))
{
pIX->Fx();
pIX->Release();
}
3) 类上下文
CoCreateInstance的第三个参数dwClsContext可以取如下值:
CLSCTX_INPROC_SERVER 客户希望创建在同一进程中运行的组件。为能够同客户在同一进程中运行,组件必须是在DLL中实现的。
CLSCTX_INPROC_HANDLER 客户希望创建进程中处理器。一个进程中处理器实际上是一个只实现了某个组件的部分的进程中组件。该组件是其他部分将由本地或远程服务器上的某个进程组件实现。
CLSCTX_LOCAL_SERVER 客户希望创建一个在同一机器上的另外一个进程中运行的组件。本地服务器是由EXE实现的。
CLSCTX_REMOTE_SERVER 客户希望创建一个在远程机器上运行的组件。此标志需要分布式COM正常工作。
执行上下文标记的一些预定义组件:
CLSCTX_INPROC CLSCTX_INPROC_SERVER、CLSCTX_INPROC_HANDLER
CLSCTX_ALL CLSCTX_INPROC_SERVER、CLSCTX_INPROC_HANDLER、CLSCTX_LOCAL_SERVER、CLSCTX_REMOVE_SERVER
CLSCTX_SERVER CLSCTX_INPROC_SERVER、CLSCTX_LOCAL_SERVER、CLSCTX_REMOVE_SERVER
演示代码:
// Client.cpp
#include
#include
void trace(const char* msg)
{
cout<<"Client: \t\t"<
}
int main(void)
{
CoInitialize(NULL);
trace("Call CoCreateInstance to create");
trace(" component and get interface IX.");
IX* pIX = NULL;
HRESULT hr = ::CoCreateInstance(CLSID_Component1,
NULL,
CLSCTX_INPROC_SERVER,
IID_IX,
(void**)&pIX);
if (SUCCEEDED(hr))
{
trace("Succeeded getting IX.");
pIX->Fx(); // Use interface IX
trace("Ask for interface IY.");
hr = pIX->QueryInterface(IID_IY,(void**)&pIY);
if (SUCCEEDED(hr))
{
trace("Succeeded getting IY.");
pIY->Fy(); // Use interface IY.
pIY->Release();
trace("Release IY interface.");
}
else
{
trace("Could not get interface IY.");
}
trace("Ask for interface IZ.");
IZ* pIZ = NULL;
hr = pIX->QueryInterface(IID_IZ,(void**)&pIZ);
if (SUCCEEDED(hr))
{
trace("Succeeded in getting interface IZ.");
pIZ->Fz();
pIZ->Release();
trace("Release IZ interface.");
}
else
{
trace("Could not get interface IZ.");
}
trace("Release IX interface.");
pIX->Release();
}
else
{
cout<<"Client: \t\tCould not create component. hr = "
<
}
CoUninitialize();
return 0;
}
类厂:
CoCreateInstance实际上并没有直接创建COM组件,而是创建了一个被称作是类厂的组件。而所需的组件正是由此类厂创建的。类厂组件的唯一功能就是创建其他的组件。
1)CoGetClassObject
函数的声明如下:
HRESULT __stdcall CoGetClassObject(
const CLSID& clsid,
DWORD dwClsContext,
CONSERVERINFO* pServerInfo, // Reserved for DCOM
const IID& iid,
void** ppv
)
2)IClassFactory
声明如下 :
interface IClassFactory:IUnknown
{
HRESULT __stdcall CreateInstance(
IUnknown* pUnknownOuter,
const IID& iid,
void** ppv
);
HRESULT __stdcall LockServer(BOOL bLock);
}
除了IClassFactory之外,Microsoft还定义了另外一个创建接口IClassFactory2。此接口在IClassFactory的基础上增加了许可权限功能。此时,为使类厂能够创建所需的组件,客户必须通过IClassFactory2给类厂提供正确的关键字或许可。通过使用IClassFactory2类厂可以保证客户只能获得它能合法访问的组件,并具有对此组件的访问授权。
3)CoCreateInstance与CoGetClassObject的比较
如何通过CoGetClassObject来实现CoCreateInstance:
HRESULT CoCreateInstance(const CLSID& clsid,
IUnknown* pUnknownOuter,
DWORD dwClsContext,
const IID& iid,
void** ppv
)
{
// Set the out parameter to NULL
**ppv = NULL;
// Create the class factory and
// get an IClassFactory interface pointer
IClassFactory *pIFactory = NULL;
HRESULT hr = CoGetClassObject(clsid,
dwClsContext,
NULL,
IID_IClassFactory,
(void**)&pIFactory);
if (SUCCEEDED(hr))
{
// create the component
hr = pIFactory->CreateInstance(pUnknownOuter,iid,ppv);
pIFactory->Release();
}
return hr;
}
4)类厂的若干特性
类厂的一个实例只能创建同某个CLSID相应的组件。
与某个特定的CLSID相应的类厂是由实现组件的开发人员实现。
类厂的实现:
1)DllGetClassObject的使用
声明如下:
STDAPI DllGetClassObject(
const CLSID& clsid,
const IID& iid,
void** ppv
);
2)流程控制
/
COM技术内幕--类厂_第1张图片
3)组件的注册
DllRegisterServer和DllUnregisterServer的作用是在Windows的注册表中登记某个组件或取消某个组件的登记。
在makefile中在CMPNT.DLL的编译和链接之后包含如下的命令:
regsvr32 -s Cmptnt.dll
函数DllRegisterServer需要包含它的DLL的模块句柄,以获取DLL的文件名并登记它。模块句柄将被传给DllMain.

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

你可能感兴趣的:(COM)