Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16498473
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 21:32:05

下载本文示例代码
  理解ATL产生的代码  我们服务器端DLL的源代码是由ATL产生的。对于许多人来说,可以完全不用了解ATL创建的代码。不过,对于一些喜欢寻根究底的人来说,这是不可以接受的。这里就介绍一下由ATL产生的代码。  服务端的DLL代码由三种不同类型的文件组成   首先,是传统的C 源文件和头文件。在开始时,所有这些代码是由ATL向导产生的   Beep方法是通过使用“AddMethod”对话框加入的,它修改了MIDL接口的定义。MIDL的源代码是一个IDL文件--在这个例子中它是BeepServer.IDL。MIDL编译器将使用该文件来创建几个输出文件。这些文件负责了大部分实现服务器的工作。当我们为COM对象加入方法时,我们也将在IDL加入一些东西。   第三组的源文件是自动产生的MIDL输出文件,是由MIDL编译器产生的。这些文件是源代码文件,不过由于它们是由MIDL编译器通过IDL源代码自动产生的,因此不能被向导或者开发者直接修改。你可以将它们称为“第二产生文件”--向导创建了一个IDL文件,而MIDL编译器由该IDL文件创建了源代码文件。由MIDL创建的文件包括有:    BeepServer.RGS - 服务器的注册脚本     BeepServer.h - 该文件包括了COM组件的定义     BeepServer_i.c - COM组件的GUID结构     Proxy/Stub files - 包括了"C"源代码、DLL定义,以及Proxy和Stub的makefile (.mk)  ATL向导还创建了一个应用的“资源”。如果你查看项目的资源,你将会发现它处在“REGISTRY”下。该资源包含了BeepServer.RGS中定义的注册脚本。资源的名字是IDR_BEEPOBJ。  我们将在以下的部分看一下这些不同的组件  主C 模块  我们在运行ATL COM Appwizard时,我们选择创建一个基于DLL的服务器,并且选择不使用MFC。向导的第一个选择屏幕决定了服务器的整体配置。  AppWizard创建了一个标准的DLL模块。该类的标准DLL并没有一个WinMain应用循环,不过它有一个DllMain函数用作在载入时初始化该DLL: CComModule _Module;BEGIN_OBJECT_MAP(ObjectMap)OBJECT_ENTRY(CLSID_BeepObj, CBeepObj)END_OBJECT_MAP()////////////////////////////////////////// DLL Entry Pointextern "C"BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/){if (dwReason == DLL_PROCESS_ATTACH){_Module.Init(ObjectMap, hInstance);DisableThreadLibraryCalls(hInstance);}else if (dwReason == DLL_PROCESS_DETACH)_Module.Term();return TRUE; // ok}  DllMain函数的真正工作是检查有没有一个客户连上该DLL,然后会做一些初始化的工作。一眼看去,并没有一个明显的指示这是一个COM应用。  我们新服务器的COM部分被封装到ATL类CComModule中。CComModule是ATL服务器的基类。它包含了所有用作登记和运行服务器、开始和维护COM对象的COM逻辑。CComModule被定义在头文件“altbase.h”中。该代码用以下的行声明一个全局的CComMoudule 对象:   CComModule _Module;  这个单一的对象包含了许多用作我们应用的COM服务器功能。它在程序执行开始时的创建和初始化设置了一连串的事件动作。  ATL需要你的服务器命名它的全局CComModule对象“_Module”。使用你自己的类来覆盖CComModule是可以的,不过你不能改变它的名字。  如果我们选择创建一个可执行的服务器,或者一个带MFC的DLL,代码将会是完全不同。这时还会有一个基于CComModule的全局对象,不过程序的入口将会是WinMain()。选择一个基于MFC的DLL将会创建一个基于CWinApp的主对象。  对象映射  CComModule通过在前面部分看到的对象映射连接到我们的COM对象(CBeepObj)。一个对象映射定义了该服务器控制的所有COM对象的一个数组。对象映射在代码中使用OBJECT_MAP宏定义。以下就是我们DLL的对象映射: BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_BeepObj, CBeepObj)END_OBJECT_MAP()  OBJECT_ENTRY宏通过一个C 类与对象的CLSID关联。一个服务器中包含有多于一个的COM对象是很常见的。这时,对于每个对象,都将会有一个OBJECT_ENTRY。  输出文件  我们这个进程内的DLL和大部分的DLL一样,都拥有一个输出文件。输出文件将被客户端用来连接到我们DLL中的外部函数。这些定义都放在BeepServer.def文件中: ; BeepServer.def : Declares the module parameters.LIBRARY "BeepServer.DLL"EXPORTSDllCanUnloadNow @1 PRIVATEDllGetClassObject @2 PRIVATEDllRegisterServer @3 PRIVATEDllUnregisterServer @4 PRIVATE  重要的是要注意到那些没有被输出的。没有用户的方法,也没有“Beep”方法的输出。以上你只看到一个COM DLL应有的输出。  查看BeepServer.CPP文件,我们可看到这4个函数的定义是由COM应用的类来处理的。以下就是DllRegisterServer的代码: // DllRegisterServer - Adds entries to the system registrySTDAPI DllRegisterServer(void){// registers object, typelib and all interfaces in typelibreturn _Module.RegisterServer(TRUE);}  在这里,DLL仅调用了ATL的CComModule::RegisterServer()方法。CComModule实现服务器注册的方法是兼容进程内、本地和远程COM服务器的。其余4个被输出的DLL函数是完全相同的。真正的实现被隐藏在ATL的模板中。  以上介绍的大部分代码是DLL的特定代码。只有在你选择创建一个基于DLL的服务器时,才会得到这个配置。主模块的代码都不是COM特定的。该主模块的体系完全是为了在一个DLL中传送COM对象,这部分的代码根据服务器类型的不同,有着明显的区别。服务器内的真正代码则是更为类似的。coclass和接口的实现是一样的,与你创建的服务器类型无关(DLL、EXE、服务器)。如果要将一个DLL服务器的coclass转换为使用一个基于EXE的服务器实现,你不需做多少的改变。共2页。 1 2 :   理解ATL产生的代码  我们服务器端DLL的源代码是由ATL产生的。对于许多人来说,可以完全不用了解ATL创建的代码。不过,对于一些喜欢寻根究底的人来说,这是不可以接受的。这里就介绍一下由ATL产生的代码。  服务端的DLL代码由三种不同类型的文件组成   首先,是传统的C 源文件和头文件。在开始时,所有这些代码是由ATL向导产生的   Beep方法是通过使用“AddMethod”对话框加入的,它修改了MIDL接口的定义。MIDL的源代码是一个IDL文件--在这个例子中它是BeepServer.IDL。MIDL编译器将使用该文件来创建几个输出文件。这些文件负责了大部分实现服务器的工作。当我们为COM对象加入方法时,我们也将在IDL加入一些东西。   第三组的源文件是自动产生的MIDL输出文件,是由MIDL编译器产生的。这些文件是源代码文件,不过由于它们是由MIDL编译器通过IDL源代码自动产生的,因此不能被向导或者开发者直接修改。你可以将它们称为“第二产生文件”--向导创建了一个IDL文件,而MIDL编译器由该IDL文件创建了源代码文件。由MIDL创建的文件包括有:    BeepServer.RGS - 服务器的注册脚本     BeepServer.h - 该文件包括了COM组件的定义     BeepServer_i.c - COM组件的GUID结构     Proxy/Stub files - 包括了"C"源代码、DLL定义,以及Proxy和Stub的makefile (.mk)  ATL向导还创建了一个应用的“资源”。如果你查看项目的资源,你将会发现它处在“REGISTRY”下。该资源包含了BeepServer.RGS中定义的注册脚本。资源的名字是IDR_BEEPOBJ。  我们将在以下的部分看一下这些不同的组件  主C 模块  我们在运行ATL COM Appwizard时,我们选择创建一个基于DLL的服务器,并且选择不使用MFC。向导的第一个选择屏幕决定了服务器的整体配置。  AppWizard创建了一个标准的DLL模块。该类的标准DLL并没有一个WinMain应用循环,不过它有一个DllMain函数用作在载入时初始化该DLL: CComModule _Module;BEGIN_OBJECT_MAP(ObjectMap)OBJECT_ENTRY(CLSID_BeepObj, CBeepObj)END_OBJECT_MAP()////////////////////////////////////////// DLL Entry Pointextern "C"BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/){if (dwReason == DLL_PROCESS_ATTACH){_Module.Init(ObjectMap, hInstance);DisableThreadLibraryCalls(hInstance);}else if (dwReason == DLL_PROCESS_DETACH)_Module.Term();return TRUE; // ok}  DllMain函数的真正工作是检查有没有一个客户连上该DLL,然后会做一些初始化的工作。一眼看去,并没有一个明显的指示这是一个COM应用。  我们新服务器的COM部分被封装到ATL类CComModule中。CComModule是ATL服务器的基类。它包含了所有用作登记和运行服务器、开始和维护COM对象的COM逻辑。CComModule被定义在头文件“altbase.h”中。该代码用以下的行声明一个全局的CComMoudule 对象:   CComModule _Module;  这个单一的对象包含了许多用作我们应用的COM服务器功能。它在程序执行开始时的创建和初始化设置了一连串的事件动作。  ATL需要你的服务器命名它的全局CComModule对象“_Module”。使用你自己的类来覆盖CComModule是可以的,不过你不能改变它的名字。  如果我们选择创建一个可执行的服务器,或者一个带MFC的DLL,代码将会是完全不同。这时还会有一个基于CComModule的全局对象,不过程序的入口将会是WinMain()。选择一个基于MFC的DLL将会创建一个基于CWinApp的主对象。  对象映射  CComModule通过在前面部分看到的对象映射连接到我们的COM对象(CBeepObj)。一个对象映射定义了该服务器控制的所有COM对象的一个数组。对象映射在代码中使用OBJECT_MAP宏定义。以下就是我们DLL的对象映射: BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_BeepObj, CBeepObj)END_OBJECT_MAP()  OBJECT_ENTRY宏通过一个C 类与对象的CLSID关联。一个服务器中包含有多于一个的COM对象是很常见的。这时,对于每个对象,都将会有一个OBJECT_ENTRY。  输出文件  我们这个进程内的DLL和大部分的DLL一样,都拥有一个输出文件。输出文件将被客户端用来连接到我们DLL中的外部函数。这些定义都放在BeepServer.def文件中: ; BeepServer.def : Declares the module parameters.LIBRARY "BeepServer.DLL"EXPORTSDllCanUnloadNow @1 PRIVATEDllGetClassObject @2 PRIVATEDllRegisterServer @3 PRIVATEDllUnregisterServer @4 PRIVATE  重要的是要注意到那些没有被输出的。没有用户的方法,也没有“Beep”方法的输出。以上你只看到一个COM DLL应有的输出。  查看BeepServer.CPP文件,我们可看到这4个函数的定义是由COM应用的类来处理的。以下就是DllRegisterServer的代码: // DllRegisterServer - Adds entries to the system registrySTDAPI DllRegisterServer(void){// registers object, typelib and all interfaces in typelibreturn _Module.RegisterServer(TRUE);}  在这里,DLL仅调用了ATL的CComModule::RegisterServer()方法。CComModule实现服务器注册的方法是兼容进程内、本地和远程COM服务器的。其余4个被输出的DLL函数是完全相同的。真正的实现被隐藏在ATL的模板中。  以上介绍的大部分代码是DLL的特定代码。只有在你选择创建一个基于DLL的服务器时,才会得到这个配置。主模块的代码都不是COM特定的。该主模块的体系完全是为了在一个DLL中传送COM对象,这部分的代码根据服务器类型的不同,有着明显的区别。服务器内的真正代码则是更为类似的。coclass和接口的实现是一样的,与你创建的服务器类型无关(DLL、EXE、服务器)。如果要将一个DLL服务器的coclass转换为使用一个基于EXE的服务器实现,你不需做多少的改变。共2页。 1 2 : 下载本文示例代码


DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五DCOM揭秘之五
阅读(156) | 评论(0) | 转发(0) |
0

上一篇:DCOM揭秘之六

下一篇:DCOM 揭秘之四 

给主人留下些什么吧!~~