首页 > 学院 > 开发设计 > 正文

CoInitializeEx、CoInitializeSecurity函数

2019-11-06 06:39:31
字体:
来源:转载
供稿:网友

0x01.CoInitializeEx函数

初始化COM库以供调用线程使用,设置线程的并发模型,并为线程创建一个新公寓(如果需要)。 如果要使用Windows运行时API,或者要使用COM和Windows运行时组件,则应调用Windows::Foundation::Initialize初始化线程而不是CoInitializeExWindows::Foundation ::Initialize足以用于COM组件。

HRESULT CoInitializeEx( _In_opt_ LPVOID pvReserved, _In_ DWord dwCoInit);

参数

pvReserved [in,optional]

此参数保留,必须为NULL。

dwCoInit [in]

线程的并发模型和初始化选项。 此参数的值取自COINIT枚举。 可以使用来自COINIT的值的任何组合,但不能同时设置COINIT_APARTMENTTHREADEDCOINIT_MULTITHREADED标志。 默认值为COINIT_MULTITHREADED

返回值

此函数可返回标准返回值E_INVALIDARGE_OUTOFMEMORYE_UNEXPECTED,以及以下值。

Return code Description
S_OK COM库已在此线程上成功初始化。
S_FALSE COM库已在此线程上初始化。
RPC_E_CHANGED_MODE 先前对CoInitializeEx的调用将此线程的并发模型指定为多线程公寓(MTA)。 这也可以表明从中线螺纹公寓到单线螺纹公寓已经发生了变化。

备注

CoInitializeEx必须至少调用一次,对于使用COM库的每个线程,它通常只调用一次。允许由同一线程对CoInitializeEx的多个调用,只要它们传递相同的并发标志,但随后的有效调用返回S_FALSE。要在线程上正常关闭COM库,每次成功调用CoInitializeCoInitializeEx(包括返回S_FALSE的任何调用)都必须通过对CoUninitialize的相应调用来平衡。 您需要在调用任何库函数(CoGetMalloc除外)之前初始化线程上的COM库,以获取指向标准分配器的指针和内存分配函数。否则,COM函数将返回CO_E_NOTINITIALIZED

在设置线程的并发模型后,不能更改。对以前初始化为多线程的公寓的CoInitialize调用将失败,并返回RPC_E_CHANGED_MODE

在单线程公寓(STA)中创建的对象仅从其公寓的线程接收方法调用,因此调用被序列化,并仅到达消息队列边界(当调用PeekMessageSendMessage函数时)。在多线程公寓(MTA)中的COM线程上创建的对象必须能够随时从其他线程接收方法调用。通常在多线程对象的代码中使用同步原语(如关键部分,信号量或互斥体)来实现某种形式的并发控制,以帮助保护对象的数据。当配置为在中性线程公寓(NTA)中运行的对象由STAMTA中的线程调用时,该线程传输到NTA。如果此线程随后调用CoInitializeEx,调用失败并返回RPC_E_CHANGED_MODE

因为OLE技术不是线程安全的,所以OleInitialize函数使用COINIT_APARTMENTTHREADED标志调用CoInitializeEx。因此,为多线程对象并发初始化的公寓不能使用OleInitialize启用的功能。

因为没有办法控制加载或卸载进程内服务器的顺序,所以不要从DllMain函数调用CoInitializeCoInitializeExCoUninitialize

Requirements

Minimum supported client Windows 2000 PRofessional[desktop apps or Windows Store apps]
Minimum supported server Windows 2000 Server [desktop apps
Minimum supported phone Windows Phone 8
Header Objbase.h
Library Ole32.lib
DLL Ole32.dll

0x02.CoInitializeSecurity函数

注册安全性并设置进程的默认安全值。HRESULT CoInitializeSecurity( _In_opt_ PSECURITY_DESCRIPTOR pSecDesc, _In_ LONG cAuthSvc, _In_opt_ SOLE_AUTHENTICATION_SERVICE *asAuthSvc, _In_opt_ void *pReserved1, _In_ DWORD dwAuthnLevel, _In_ DWORD dwImpLevel, _In_opt_ void *pAuthList, _In_ DWORD dwCapabilities, _In_opt_ void *pReserved3);

参数

pSecDesc [in,optional]

服务器将用于接收呼叫的访问权限。 只有当服务器调用CoInitializeSecurity时,COM才使用此参数。 它的值是一个指向三种类型之一的指针:一个AppID,一个IaccessControl对象或一个SECURITY_DESCRIPTOR,以绝对格式。

cAuthSvc [in]

asAuthSvc参数中的条目计数。 只有当服务器调用CoInitializeSecurity时,COM才使用此参数。 如果此参数为0,则不会注册认证服务,并且服务器无法接收安全呼叫。 值-1指示COM选择要注册的认证服务,如果是这种情况,则asAuthSvc参数必须为NULL。 但是,如果此参数为-1,则Schannel将永远不会被服务器选为认证服务。

asAuthSvc [in,optional]

服务器愿意用于接收呼叫的身份验证服务数组。 只有当服务器调用CoInitializeSecurity时,COM才使用此参数。 有关详细信息,请参阅SOLE_AUTHENTICATION_SERVICE

pReserved1 [in,optional]

此参数保留,必须为NULL

dwAuthnLevel [in]

进程的默认身份验证级别。服务器和客户端在调用CoInitializeSecurity时都使用此参数。 COM将失败以较低认证级别到达的呼叫。默认情况下,所有代理将至少使用此身份验证级别。此值应包含一个认证级别常量。默认情况下,所有对IUnknown的调用都是在此级别进行的。

dwImpLevel [in]

代理的默认模拟级别。此参数的值仅在进程是客户端时使用。它应该是来自模拟级别常量的值,RPC_C_IMP_LEVEL_DEFAULT除外,不能与CoInitializeSecurity一起使用。

来自客户端的拨出呼叫始终使用指定的模拟级别。 (不是协商的。)对客户端的来电可以是任何模拟级别。默认情况下,所有IUnknown调用都使用此模拟级别,因此即使安全感知应用程序也应仔细设置此级别。要确定每个认证服务支持的模拟级别,请参阅COM和安全软件包中的认证服务的描述。有关模拟级别的详细信息,请参阅模拟。

pAuthList [in,optional]

指向SOLE_AUTHENTICATION_LIST的指针,它是一个SOLE_AUTHENTICATION_INFO结构的数组。此列表指示客户机可用于调用服务器的每个认证服务的信息。只有当客户端调用CoInitializeSecurity时,COM才使用此参数。

dwCapabilities [in]

通过设置一个或多个EOLE_AUTHENTICATION_CAPABILITIES值指定的客户端或服务器的其他功能。其中某些值不能同时使用,有些不能在使用特定认证服务时设置。有关这些标志的更多信息,请参阅备注部分。

pReserved3 [in,可选]

此参数保留,必须为NULL。

返回值

此函数可以返回标准返回值E_INVALIDARG以及以下值。

Return code Description
S_OK 表示成功。
RPC_E_TOO_LATE CoInitializeSecurity已被调用。
RPC_E_NO_GOOD_SECURITY_PACKAGES asAuthSvc参数不为NULL,并且列表中的所有身份验证服务都不能注册。 检查保存在asAuthSvc中的结果以获取身份验证服务特定的错误代码。
E_OUT_OF_MEMORY 内存不足。

备注

CoInitializeSecurity函数初始化安全层,并将指定的值设置为安全性默认值。如果进程不调用CoInitializeSecurity,则COM在第一次编组或解组接口时自动调用它,注册系统默认安全性。之前没有注册默认安全软件包。

这个函数每个进程只被调用一次,无论是显式还是隐式。它可以由客户端,服务器或两者调用。对于没有显式调用CoInitializeSecurity的传统应用程序和其他应用程序,COM使用注册表中的值隐式调用此函数。如果使用注册表设置过程范围安全性,然后调用CoInitializeSecurity,那么将忽略AppID注册表值,并使用CoInitializeSecurity值。

CoInitializeSecurity可用于覆盖计算机范围的访问权限和特定于应用程序的访问权限,但不能覆盖计算机范围的限制策略。 如果pSecDesc指向AppID,则必须在dwCapabilities中设置EOAC_APPID标志,并且当设置EOAC_APPID标志时,将忽略CoInitializeSecurity的所有其他参数。

CoInitializeSecurity在注册表中的AppID键下查找认证级别,并使用它来确定默认安全性。有关如何使用AppID密钥设置安全性的更多信息,请参阅通过注册表设置流程范围的安全性。 如果pSecDesc是指向IAccessControl对象的指针,则必须设置EOAC_ACCESS_CONTROL标志,并且dwAuthnLevel不能为noneIAccessControl对象用于确定谁可以调用进程。 DCOMAddRef IAccessControl,并将在调用CoUninitialize时释放它。不应更改IAccessControl对象的状态。

如果pSecDesc是指向SECURITY_DESCRIPTOR的指针,则在dwCapabilities中不能设置EOAC_APPIDEOAC_ACCESS_CONTROL标志。必须设置SECURITY_DESCRIPTOR的所有者和组,直到DCOM支持审核,系统ACL必须为NULLSECURITY_DESCRIPTOR的自由ACLDACL)中的访问控制条目(ACE)用于查找允许哪些调用者连接到进程的对象。没有ACEDACL不允许访问,而NULL DACL将允许任何人的调用。有关ACLACE的更多信息,请参阅访问控制模型。应用程序应调用AccessCheck(而不是IsValidSecurityDescriptor),以确保在调用CoInitializeSecurity之前正确形成其SECURITY_DESCRIPTOR

强烈建议不要将pSecDesc传递为NULL。一个适当的替代方法是使用允许EveryoneSECURITY_DESCRIPTOR。如果pSecDescNULL,dwCapabilities中的标志确定CoInitializeSecurity如何定义服务器将使用的访问权限,如下所示:

如果设置了EOAC_APPID标志,CoInitializeSecurity将在注册表中查找应用程序的.exe名称,并使用存储在那里的AppID。如果设置了EOAC_ACCESS_CONTROL标志,CoInitializeSecurity将返回错误。如果既没有设置EOAC_APPID标志也没有设置EOAC_ACCESS_CONTROL标志,CoInitializeSecurity允​​许所有呼叫者,包括本地和远程匿名用户。

如果在dwCapabilities中设置了EOAC_APPIDEOAC_ACCESS_CONTROL标志,则CoInitializeSecurity函数返回错误。

函数库文件同上。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表