COM原理
+ -

COM组件的安装与卸载

2022-02-08 31 0

(1)进程内组件的安装

客户调用COM库的CoCreateInstance或CoGetClassObject创建COM对象时,在CoGetClassObject中,COM库根据注册表中的信息,找到类标识符CLSID对应的组件程序(DLL)的全路径并调用CoLoadLibrary,再调用组件程序的DllGetClassObject导出函数。

如:ASIO asiosample.dll注册及注册表信息变化

DllGetClassObject创建相应的类厂对象,并返回类厂对象的IClassFactory接口。至此CoGetClassObject任务完成,然后客户程序或CoCreateInstance继续调用类厂对象的CreateInstance成员函数,由它负责COM对象的创建工作。

如:ASIO 驱动加载loadAsioDriver的AsioDrivers::loadDriver功能。

(2)进程外组件的安装

在COM库的CoGetClassObject中,当发现组件程序是EXE(由注册表组件对象信息中的LocalServer或LocalServer32值指定)时,COM库创建一个进程启动组件程序,并带上/Embedding命令行参数,然后等待组件程序;组件程序启动后,当它检查到/Embedding命令行参数时,就会创建类厂对象,然后调用CoRegisterClassObject把类厂对象注册到COM中。

当COM库检查到组件对象的类厂之后,CoGetClassObject就返回类厂对象。由于类厂与客户运行在不同进程中,所以客户程序得到的是类厂的代理对象。一旦客户程序或COM库得到了类厂对象,就可完成组件对象的创建工作。进程内对象和进程外对象的不同创建过程仅仅影响了CoGetClassObject的实现过程,对客户程序来说是完全透明的。

(3)进程内组件的卸载

只有当组件程序满足了两个条件时,它才能被卸载,这两个条件是:组件中对象数为0,类厂的锁计数为0。满足这两个条件时,DllCanUnloadNow导出函数返回TRUE。

COM库提供了CoFreeUnusedLibraries,它会检测当前进程中的所有组件程序,当发现某个组件程序的DllCanUnloadNow返回TRUE时,就调用FreeLibrary(实际是CoFreeLibrary)把该组件从内存中卸出。由谁来调用CoFreeUnusedLibraries呢?因为组件执行过程中它不可能把自己从内存中卸出,所以这个任务应该由客户完成。客户程序随时都可调用CoFreeUnusedLibraries完成卸载工作,通常做法是,在程序空闲处理过程中调用CoFreeUnusedLibraries,这样做既可避免程序中处处考虑对CoFreeUnusedLibraries的调用,又可使不再使用的组件程序得到及时清除,提高了资源的利用率,COM规范也推荐这种做法。

(4)进程外组件的卸载

进程外组件的卸载比较简单,因为组件程序运行在单独的进程中,一旦其退出的条件满足,它只要从进程的主控函数返回即可。在Windows系统中,进程的主控函数为WinMain。
前面曾说过,在组件程序启动运行时,它调用CoRegisterClassObject函数,把类厂对象注册到COM中,注册之后,类厂对象的引用计数始终大于0,因此单凭类厂对象的引用计数无法控制进程的生存期,这也是引入类厂对象的加锁和减锁操作的原因。进程外组件的卸载条件与DllCanUnloadNow中的判断类似,也需要判断COM对象是否存在、以及判断是否锁计数器为0,只有当条件满足了,进程的主函数才可退出。

从原则上讲,进程外组件程序的卸载就是这么简单,但实际情况可能复杂一些,因为有些组件程序在运行过程中可创建自己的对象,或包含用户界面的程序在运行过程中,用户手工关闭了进程,那么进程对这些动作的处理要复杂一些。
例如,组件程序在运行过程中,用户又打开了一个文件并进行操作,那么即使原先创建的对象被释放了,而且锁计数器也为0,进程也不能退出,它必须继续为用户服务,就像是用户打开的进程一样。对这种程序,可增加一个”用户控制”标记flag,如果flag=FALSE,则可按简单方法直接退出程序即可;如果flag=TRUE,则表明用户参与了控制,组件进程不能马上退出,应该调用CoRevokeClassObject以便与CoRegisterClassObject调用相呼应,把进程留给用户继续进行。

如果组件程序在运行过程中,用户要关闭进程,而此时并不满足进程退出条件,那么进程可采取两种办法:第一种方法,把应用隐藏起来,并设置flag=FALSE,然后组件程序继续运行直到卸载条件满足为止;另一种办法是调用CoDisconnectObject,强迫脱离对象与客户之间的关系,并强行终止进程,这种方法比较粗暴,不提倡采用,但不得已时也可使用,以保证系统完成一些高优先级的操作。

0 篇笔记 写笔记

Windows Inf文件设备GUID分类(设备安装程序类)
Class=SystemClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}Class=USBClassGuid={36FC9E60-C465-11CF-8056-444553540000}Class=AudioClassGuid={4d36e96c-......
卸载驱动IopUnloadDriver
内核卸载驱动调用的函数是NtUnloadDriver,这个函数只是对IopUnloadDriver的包装。NTSTATUS NTAPINtUnloadDriver(IN PUNICODE_STRING DriverServiceName){ return IopUnloadDriver(......
分发函数与卸载函数
DRIVER_OBJECT中含有分发函数指针。这些函数用来处理发到这个驱动的各种请求。Windows总是自己调用DRIVER_OBJECT下的分发函数来处理这些请求。所以编写一个驱动程序,本质就是自己编写这些处理请求的分发函数。DRIVER_OBJECT下的分发函数指针的个数为IRP_MJ_MAX......
windows驱动协安装的配置及源安装路径获取
在做windows驱动开发时,有时需要在驱动安装前,安装后,等事件发生时进行一系列的处理工作,当然如果在驱动内部配置相关的IRP回调函数,但有时多有不便。微软给我们提供了一种叫做协安装的方法,由系统调用,我们只需要生成DLL并导出函数即可。以vm虚拟机的显卡驱动为例,inf文件配置如下:[vmx......
windows驱动协安装路径获取
在做windows驱动开发时,有时需要在驱动安装前,安装后,等事件发生时进行一系列的处理工作,当然如果在驱动内部配置相关的IRP回调函数,但有时多有不便。微软给我们提供了一种叫做协安装的方法,由系统调用,我们只需要生成DLL并导出函数即可。以vm虚拟机的显卡驱动为例,inf文件配置如下:[vmx......
WDDM 停止、复位、移除设备及驱动卸载
说完了驱动的创建与启动,这里顺使说一下设备的停止、复位、卸载设备设备的停止/BddDdiStopDevice设备停止的回调函数为BddDdiStopDevice InitialData.DxgkDdiStopDevice = BddDdiStopDevi......
devcon update/remove命令(更新/安装/卸载驱动)
这里的inf文件为:pnpon.inf硬件ID为:*PNPONVDualA可根据需要自行修改CD /d %~dp0devcon.exe update pnpon.inf "*PNPONVDualA"echo %errorlevel% if %errorlevel% ......
PDO设备的动态创建与卸载IRP_MN_SURPRISE_REMOVAL和IRP_MN_REMOVE_DEVICE
总线驱动创建的PDO在卸载时,因卸载方式不同而不同如果是直接卸载总线,会只调用IRP_MN_REMOVE_DEVICE而如果是动态创建与卸载,在卸载的时候调用IoInvalidateDeviceRelations会导致IRP_MN_SURPRISE_REMOVAL的调用,然后调用IRP_MN_R......
SetupDi 驱动安装函数
DiInstallDeviceInstalls a specified driver that is preinstalled in the driver store on a PnP device that is present in the system. (WindowsVista a......
SetupDi 驱动安装处理函数
SetupDiCallClassInstallerCalls the appropriate class installer, and any registered co-installers, with the specified installation request.Set......
COM对象的创建
在COM库中有3个可用于创建COM对象的函数,分别是CoGetClassObject和CoCreateInstnace/Ex。通常情况下,客户程序调用其中之一完成对象的创建,并返回对象的初始接口指针。COM库与类厂也通过这3个函数进行交互。CoGetClassObjectHRESULT CoGet......
COM组件的安装卸载
(1)进程内组件的安装客户调用COM库的CoCreateInstance或CoGetClassObject创建COM对象时,在CoGetClassObject中,COM库根据注册表中的信息,找到类标识符CLSID对应的组件程序(DLL)的全路径并调用CoLoadLibrary,再调用组件程序的Dll......
Windows驱动安装过程
手动安装驱动程序,把sys/inf等文件安装到系统中.winddk示例目录src/setup/devcon提供了预安装驱动的方法。编译后,可以通过devcon install path_to_inffile hwid的方式安装驱动程序或通过devcon update path_to_inffile......
挂起的IPR在卸载驱动中的处理
有时有一种情况,说是会将上层如CAMERA,HID等USB设备下发的IPR进行入链表LIST_ENTRY,当然在入之前,会将此IRP 挂起pending,并设置取消例程。不过在驱动卸载的时候,或者某种情况下需要手动清除这些IRP时,会出现和CANCEL例程竞争的情况。故这些需要进行一些判断再处理:......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!