文件系统驱动编程基本篇之4——Wmi打点类型
副标题#e#
二、WMI简介
一)基于Web的企业打点(Web-Based Enterprise Management (WBEM))的提出是为了办理企业在快速成长的进程中,总本钱(Total cost of ownership(TCO)) 也随之快速增长的抵牾,它作为一项业界倡议,起始于1996年,类型了企业网络中受管资源的描写与利用。WBEM成立在通用信息模子(Common Information Model (CIM, 由Desktop Management Task Force,即DMTF敦促的家产化尺度))筹划(schema)的基本上。WBEM提出了一个尺度化的的要领用于成立统一的框架,差异技能僻静台上发生的打点信息均以沟通的形式供打点措施会见,这样就淘汰了维护用度和企业网络的寿命周期本钱(life cycle costs)。(注:Common除了译为“通用”,也可译为“民众”)
从基础上说,WBEM提供了数据界说的信息尺度和组件交互的处理惩罚尺度。
二)CIM是一种机制,用于为受管资源建模并以受管工具名目(Managed Object Format (MOF))表示这些模子。利用 CIM 和 MOF,构成受管资源或资源网络的组件可以象在面向工具设计进程中利用的组件一样被建模和对待。
CIM由一个焦点模子,很多通用模子以及扩展模子构成。焦点模子是一系列类、毗连和属性的荟萃,该工具组提供了所有打点域公用的根基信息模子;通用模子提供特定打点域的通用信息模子,这些特定的打点域,如系统、应用措施、设备、用户和网络等;扩展模子代表通用模子的特定技能扩展。
A core model—incorporates classes applicable to all management domains.
Common models—incorporate classes common to specific management domains, independent of particular technologies or implementations. Common domains include systems, applications, devices, users, and networks. These models provide a basis for the development of management applications and include a set of base classes for extension into technology-specific areas.
Extension models—these represent technology-specific extensions of the common models. These models are specific to environments, such as operating systems (for example, UNIX, or Microsoft Windows).
三)Windows Management Instrumentation——凡是译为WMI打点类型,是微软提出的,与WBEM兼容的技能,同样也兼容于CIM2.0或2.5。WMI是Windows打点处事的主要组件,它提供的成果如下(从资料2节选,重点影象红字即可mcieels):
A rich and consistent model of Windows 98 and Windows 2000 operation, configuration, and status. 是一个模子
A COM API that supplies a single point of access to all management information. 可COM会见
Interoperability with other Windows 2000 management services, which will simplify vendors’ efforts to create well-integrated management applications. 可协作
A flexible architecture that allows vendors to extend the information model to cover new devices, applications, and other enhancements by writing code modules (WMI providers). 可扩展
A powerful event architecture that allows changes in management information to be identified, aggregated, compared to and associated with other management information, and forwarded to local or remote management applications. 有事件机制
A rich query language(WQL) that enables detailed queries of the information model. 可查询
A scriptable API, which enables management application developers to use Visual Basic? or Windows Script Host (WSH). 可剧本会见
#p#副标题#e#
图10-2是上图架构的简化,在WMI模子中,数据和事件被分成了消费者(Consumers)和出产者(Providers)两类。数据块就是抽象类的实例,其观念与C++中的类观念一致。如同C++中的类,WMI类也有数据成员和实现工具行为的要领。数据块中的内容并不是由WMI指定,而是由数据出产者和数据的利用目标抉择的。送往驱动措施的数据最有大概来自打点者自己的操纵。而驱动措施发出的数据凡是是某种机能的统计数据,这些数据的消费者大概是某本机能监督措施。
WMI类答允同时存在全球化和当地化的数据,详看资料3。
WMI类又可称为主类(master class),由基类(basic class)和amendment(批改,更正之意,用于当地化,难以料到符合的译文^_^)类构成。主类包括所有的属性集和限定(qualifiers)。基类是主类的子集,包括所有的属性集和部门限定,不包括当地限定(localizable qualifiers)。amendment和主类具有沟通的名字,是一个抽象类,包括了关于当地限定的属性子集(includes a subset of properties with localizable qualifiers),不包括主类的其他属性。
#p#分页标题#e#
amendment老是位于包括基类界说的定名空间下的子定名空间。每一个子定名空间包括着出格当地化(particular locale)的amendment类,这样设计的功效是多种语言的子定名空间可以被插手到储存库(repository,见架构图)中,因此可同时存在多种语言的类界说:
ROOT\CIMV2
ROOT\CIMV2\MS_409
ROOT\CIMV2\MS_407
WMI答允存在多重定名空间,每个定名空间中包括的类属于一个或多个用户模式出产者。出产者利用平台SDK中果真的COM接口来注册Windows打点处事(Windows Management Service)。操纵系统(包罗所有设备驱动措施)支持一个名为root\cimv2的定名空间,内里包括了CIM版本2。
四)WDM驱动措施可以作为WMI类实例的出产者。一个描写了驱动措施支持的各类类(驱动措施可觉得这些类提供数据)的剧本称为驱动措施筹划(schema)。我们可以利用MOF(Managed Object Format)语言界说筹划。系统则维护一个称为储存库(repository)的数据字典,它包括了所有已知的筹划界说。假如驱动措施做得正确,系统将在初始化驱动措施时自动把筹划放到储存库中。
WDM出产者是WMI出产者的一个构成部门,它可以会见WDM硬件驱动的类、实例、要领和事件。硬件驱动的类位于root\wmi定名空间,Wmi.mof和Wmicore.mof界说了主要的WDM类。WDM出产者答允打点措施从满意WMI-for-WDM的设备驱动会见数据和事件,出产者主要以IWbemServices接口的形式提供这些处事。
为了查察定名空间,可到微软站点下载安装WMITools软件。WMI CIM Studio以树视图的形式揭示了分层的定名空间。
三、MOF与WQL语言
MOF是一种基于接口界说语言 (IDL) 的语言,用于描写打点信息,即用于描写CIM。MOF 语法是以文本形式描写工具界说的要领。MOF 汇编器(如mofcomp.exe)处理惩罚 MOF 文件,并向 CIM 储存库添加必须的工具界说。C++Builder范例库(Type Library)也利用了IDL。
MOF语法雷同于C++,但远比C++简朴,假如在进修进程中碰着坚苦,可以遐想两者的相似处。如MOF类的实例化可以想象成C++的结构函数,引用也可以遐想成C++的&。
一个简朴的MOF文件master.mof如下:
MOF和C++类界说有相似之处,也利用#pragma预处理惩罚。#pragma amendment指示编译器输出语言中性和语言特定的两个版本,“MS_409”暗示当地标识符(LCID),雷同尚有“MS_408”等。
MOF的数据范例见资料10。
MOF包括了富厚的限定(Qualifier ,[ ]里以逗号脱离的标识符),用于描写类、实例、属性、要领和要领的参数。限命名不区分巨细写,除此之外,它还遵守雷同于C++定名的一些约束。限定可分为三大类:尺度限定(Standard qualifier),CIM限定(CIM qualifier),非凡限定(Unique qualifier),你还可觉得本身的出产者建设自界说的限定。
限定可以被称为“限定气势气魄”(Qualifier Flavor)的符号来修饰,语法为:
[qualifier1 : flavor1 flavor2 flavor3, qualifier2 : flavor1]
因此,综合了限定以及限定气势气魄的分类后也可举办如下的分别(*为WDM里常见):
Qualifier Type | Description | 注释 |
Meta | Refines the definition of meta-constructs by clarifying the actual usage of a class or property declaration. | 通过MOF语法阐发类或属性声明的实际用途,元限定完善了CIM模式元布局的界说。 |
Standard* | Supports the descriptions that all CIM-compliant implementations must handle. | |
Optional | Addresses situations not common to all CIM-compliant implementations. | |
WMI-specific* | Describes qualifiers specific to WMI, such as performance counter class qualifiers. | |
Qualifier Flavors | Provides additional information about a qualifier, such as whether a derived class or instance can override the qualifier’s original value. |
一些限定与气势气魄:
Qualifier | 分类 | 注释 | 示例 |
Amended | Flavor | 基类不消该限定,amendment类用于当地化 | DisplayName("User Name") : Amended |
Amendment | WMI-specific – Standard | 指明类里包括被当地化的amended限定 | Amendment |
Description | Standard | 描写了被定名的元素,默认为NULL | Description("This property shows when the object was created") |
DisplayName | Standard | 取代真实的元素名而显示在UI的名字 | DisplayName("Time Stamp") |
Dynamic | WMI-specific – Standard | 指明类的实例被动态建设 | Dynamic |
Guid | 自界说 | 必需,驱动措施用来分辨出产者 | 见wmi42.mof |
Key* | Standard | 键属性用来标识和区分每一个实例 | Key |
Locale | WMI-specific – Standard | 为类或实例指定语言 | Locale(0x409) |
Provider | WMI-specific – Standard | 限定的值是动态出产者的名字,出产者建设类实例和更新实例数据 | Provider("WMIProv") |
WMI | 自界说 | 暗示出产者范例 | 见wmi42.mof |
WmiDataId | WMI-specific – WDM | Index in the WNODE of the data for the property. The WDM provider uses this qualifier to determine how the data is formatted while extracting data from the WNODE and generating WMI classes. The starting value is 1. (除了InstanceName和Active属性,其他属性都必需带有该Id) | WmiDataId(1) |
* Key:Msdn上存在抵牾的说明。错误的说明是认为仅InstanceName能被声明为Key,但实际上可由多个属性构成复合键。
对付难以领略的限定,可通过CIM Studio来查察实际的结果。如属于Meta类此外Association是一个难以琢磨的限定,请看下面的mof文件:
<// 本文转自 C++Builder研究 – http://www.ccrun.com/article.asp?i=1057&d=d1f203
/p>
#p#分页标题#e#
#pragma namespace("\\\\.\\root") instance of __Namespace
{
Name = "WMI" ;
} ;
#pragma namespace("\\\\.\\root\\WMI")
Class A{
[key] string aKey;
};
Class C{
[key] string cKey;
};
Class D{
[key] string dKey;
};
Class E{
[key] string eKey;
};
// The following class creates an association between the "A", "C", "D", "E" class
[Association] Class B{
[key] A ref aRef;
[Key, Min(1)] C ref cRef;
[key] D ref dRef;
[key] E ref eRef;
};
它在定名空间root\wmi下建设了A、B、C、D、E五个类,它们的Association干系别离为:
MOF汇编器常用的三种操纵:
查抄MOF文件语法:mofcomp –check master.mof
建设语言中性和语言特定的MOF文件:mofcomp -MOF:g.mof -MFL:l.mof master.mof
编译成二进制的BMF文件,该文件可以自界说资源的方法插手C++工程的资源文件中:mofcomp –B: bin.bmf l.mof
// g.mof,0x409 = 1033
[LOCALE(1033)]
class myclass
{
[key] string Name;
uint64 Value;
uint64 Timestamp;
};
// l.mof
#pragma namespace("\\\\.\\root\\default")
instance of __namespace{ name="ms_409";};
#pragma namespace("\\\\.\\root\\default\\ms_409")
[Description("Localized version of MyClass for American English") : Amended,AMENDMENT, LOCALE(0x409)]
class myclass
{
[DisplayName("User Name") : Amended,Description("The Name property contains the name of the user") : Amended,key] string Name;
[DisplayName("Time Stamp") : Amended,Description("This property shows when the object was created") : Amended] uint64 Timestamp;
};
注释// 或 /* */并非可到处添加,如汇编器提示“…文件域意外的标记…”时要出格留意注释是否放于错误的位置上。
instance of __namespace一行实例化了ms_409定名空间(即root\DEFAULT\ms_409),下一行则在这个定名空间加载myclass类。
通过语法查抄的mof文件可以插手WMI定名空间(N暗示默认加载的空间):
mofcomp -N:root\default g.mof
#p#分页标题#e#
利用CIM Studio查察储存库里的g.mof,对付l.mof,Value不会呈此刻属性表中:
通过CIM Studio里的MOF Generator东西还可以生成你感乐趣的节点的MOF文件。
请阅读如下toaster.mof,领略包括的语法,并在WMI定名空间下验证本身的领略:
[Dynamic, Provider("WMIProv"),
WMI,
Description("Toaster driver information"),
guid("{BBA21300-6DD3-11d2-B844-00C04FAD5171}"),
locale("MS\\0x409")]
class ToasterDeviceInformation
{
[key, read]
string InstanceName;
[read] boolean Active;
[WmiDataId(1),
read,
WmiEnum{"0=I8042 Connector"
"1=Serial Connector",
"2=Parallel Connector",
"3=USB Connector" },
Description("How the toaster is connected to the computer")]
uint32 ConnectorType;
[WmiDataId(2),
read,
Description("This indicates the capacity in Kilo Watts of the toaster device.")]
uint32 Capacity;
[WmiDataId(3),
read,
Description("Number of errors that occurred on this device")]
uint32 ErrorCount;
[WmiDataId(4),
read,
Description("Indicates the number of controls on the toaster device.")]
uint32 Controls;
[WmiDataId(5),
read,
write,
Description("The DebugPrintLevel property indicates the debug output level of toaster device.")]
uint32 DebugPrintLevel;
[WmiDataId(6),
read,
Description("ModelName")]
string ModelName;
};
[WMI, Dynamic, Provider("WMIProv"),
guid("{01CDAFF1-C901-45b4-B359-B5542725E29C}"),
locale("MS\\0x409"),
WmiExpense(1),
Description("Notify Toaster Arrival")]
class ToasterNotifyDeviceArrival : WMIEvent
{
[key, read]
string InstanceName;
[read]
boolean Active;
[read,
Description("Device Model Name"),
WmiDataId(1)] string ModelName;
};
为相识系统默认生成的定名空间,可阅读system32\wbem路径下的MOF文件。为了把握MOF的语法,可阅读DDK源代码目次下的MOF文件。
WQL是Ansi-SQL的简化版本,它可以用来查询定名空间下的类,如select * from wmi42,对此不再详述。
四、WMI与驱动措施
请先阅读资料1第二节,以及wmi42示例的SYS部门。
驱动措施对WMI的支持,表此刻对系统节制IRP,即IRP_MJ_SYSTEM_CONTROL的支持上。除了以Ioctl雷同的方法实现该IRP(AltWmi.cpp),更简朴的方法是委托WMILIB来支持WMI(Wmi.cpp),这涉及到一个数据布局:
// This structure supplies context information for WMILIB to process the
// WMI irps. Memory for this structure may be paged.
typedef struct _WMILIB_CONTEXT
{
// WMI data block guid registration info
ULONG GuidCount;
PWMIGUIDREGINFO GuidList;
// WMI functionality callbacks
PWMI_QUERY_REGINFO QueryWmiRegInfo;
PWMI_QUERY_DATABLOCK QueryWmiDataBlock;
PWMI_SET_DATABLOCK SetWmiDataBlock;
PWMI_SET_DATAITEM SetWmiDataItem;
PWMI_EXECUTE_METHOD ExecuteWmiMethod;
PWMI_FUNCTION_CONTROL WmiFunctionControl;
} WMILIB_CONTEXT, *PWMILIB_CONTEXT;
Wmi.cpp是如那里理惩罚WMI请求的?针对系统节制IRP里的几个副成果码,我们界说了相应的回调函数,WMILIB_CONTEXT布局里的回调函数指针指向我们的函数。当WMI调派例程DispatchWmi挪用WmiSystemControl来处理惩罚IRP时,就会自动挪用这些函数。AddDevice和RemoveDevice例程挪用IoWMIRegistrationControl为设备工具注册或注销作为WMI数据出产者(WMI data provider)的驱动措施。注册之后,第一个被处理惩罚的系统节制IRP的副成果码是IRP_MN_REGINFO,调派函数QueryRegInfo被挪用以处理惩罚该成果码。在QueryRegInfo里,返回了系统用于建设数据块的MOF资源的名字。其他调派函数就此略过,Msdn里对每个函数都有具体的论述。
#p#分页标题#e#
Wmi42正确启动后应该切合下图的景象(假如在安装上遇到问题,可临时跳过,下篇将对安装问题作进一步的说明):
留有余力的读者,可进一步研究WMI的事件机制,在此略过。
五、WMI、COM与用户措施
请阅读资料1第三节,以及Chap10\WMI42示例的TEST部门。
本篇是初次涉及COM编程,此后我们还将连续打仗COM在各规模的应用。COM既是一种技能,也是一种组件,这种组件对外果真了一些称为“接口”的抽象类,除此以外都是不透明的。如果我们剖开外壳可以看到内部的实体,即不是接口的那些类,由被称为“类厂”的类来建设(即用类来建设类)。实体通过接口对外提供了COM的所有处事。接口、实体、类厂可当作COM组件的根基元素。
接口的利用有一个很重要的约定——每每查询/获取一次接口,都要用AddRef()增加一次计数,接口利用后都要用Release()释放本次计数。有时候我们利用API函数后没有挪用AddRef(),却需要Release(),原因是这些函数内部已有挪用代码。这样的常用API并没有几个,我们可以通过实践很快的把握,一些不确定是否需要释放计数,以及如何释放计数的API可以查阅Msdn。
COM呈现后不久,一些“懒人”写出了自动维护约定的智能指针,随后ATL呈现了。客观的说,微软在技能上的创新孝敬是有目共睹的,可是ATL?它把所有看到的对象一律封装成模板,这样你可以仅用ATL就可以完成一个实用的Windows措施了,它的技能书籍重得甚至可拿来压舱底。对比大大都人的敬而远之,微软固然也在逐渐淡化COM,但即便如此,本日许多的新生技能外表下都埋没着COM。
WMI也是通过COM接口提供处事,详见资料11。
TEST示例首先初始化COM和为历程配置了默认的安详值,接着打开root\wmi定名空间,配置接口权限,最后陈诉Wmi42类属性的信息。
在此例的基本上,可深入进修种种接口函数,弄清MOF语法如何故COM接口方法挪用。
代码《let_us_try_wmi_samples》,《WMI C++ Application Examples》演示了如何利用WMI会见常见硬件,后篇系统的总结了用户模式下挪用WMI的根基步调。另可阅读Msdn上关于Vista下利用WMI的阐述。
六、IClientSecurity接口与安详
vs2005的Msdn里并没有IClientSecurity接口的说明(官方站点有此说明的),既然微软好像有意健忘了,笔者也实在不肯耗费时间陷入细节中去,我们可在在实践中来体会该接口的成果。
IClientSecurity
Gives the client control over the security settings for each individual interface proxy of an object. The methods of IClientSecurity can be used to set or query the security settings of a specific interface proxy or to copy an interface proxy.
Every object has one proxy manager, and every proxy manager exposes the IClientSecurity interface automatically. Therefore, the client can query the proxy manager of an object for IClientSecurity, using any interface pointer on the object. If the QueryInterface call succeeds, the IClientSecurity pointer can be used to call an IClientSecurity method, passing a pointer to the interface proxy that the client is interested in. If a call to QueryInterface for IClientSecurity fails, either the object is implemented in-process or it is remoted by a custom marshaler that does not support security. (A custom marshaler can support security by offering the IClientSecurity interface to the client.)
The interface proxies passed as parameters to IClientSecurity methods must be from the same object as the IClientSecurity interface. That is, each object has a distinct IClientSecurity interface: calling IClientSecurity on one object and passing a proxy to another object will not work. Also, you cannot pass an interface to an IClientSecurity method if the interface does not use a proxy. This means that interfaces implemented locally by the proxy manager cannot be passed to IClientSecurity methods, except for IUnknown, which is the exception to this rule.
For more information about proxies, see IMarshal – Default Implementation.
When to Implement
The proxy manager for each object provides an implementation of IClientSecurity, so you would typically not implement this interface. If, however, you are defining objects that support custom marshaling, you may choose to implement IClientSecurity on the objects’ custom proxies to maintain a consistent programming model for the objects’ client applications. You may also choose to support this interface on in-process objects.
When to Use
#p#分页标题#e#
Call the methods of this interface to examine or modify the security settings of a particular connection to an out-of-process object. For example, you might temporarily establish a higher security level — one with complex encryption — only for the period when sensitive information or data is being sent to the object. Alternately, you might establish different proxies to the same object with different security levels. You could use these security levels to support different clients that are calling your object or to support different operations within your application.
Methods in Vtable Order
IClientSecurity Methods | Description |
QueryBlanket | Retrieves authentication information. |
SetBlanket | Sets the authentication information that will be used to make calls on the specified proxy. |
CopyProxy | Makes a copy of the specified proxy. |
七、结语
除了Ioctl,此刻我们又把握了一个相识系统的重要手段,读者在存眷WMI细节的同时,也请寄望一下系统性的事物如何把各个分系统举办整合。
本篇作为选读内容,不设参考完成时间。