将范围访问与 WpdServiceSampleDriver (属性命令)
示例驱动程序支持六个属性命令。 这些命令最初由 WpdObjectProperties::D ispatchMessage 方法处理,该方法又调用相应的命令处理程序。 DispatchMessage 方法和各个处理程序都位于 WpdObjectProperties.cpp 文件中。
下表描述了每个支持的属性命令,以及 DispatchMessage 处理给定命令时调用的处理程序的名称。
命令 | Handler | 说明 |
---|---|---|
WPD_COMMAND_OBJECT_PROPERTIES_GET_SUPPORTED | OnGetSupportedProperties | 返回给定对象的属性键数组。 |
WPD_COMMAND_OBJECT_PROPERTIES_GET | OnGetPropertyValues | 返回属性值的集合,这些值对应于提供给驱动程序的属性键。 |
WPD_COMMAND_OBJECT_PROPERTIES_GET_ALL | OnGetAllProperties | 返回给定对象的所有属性值。 |
WPD_COMMAND_OBJECT_PROPERTIES_SET | OnSetPropertyValues | 设置设备上指定的属性值。 |
WPD_COMMAND_OBJECT_PROPERTIES_GET_ATTRIBUTES | OnGetPropertyAttributes | 返回给定对象上一个或多个属性的属性集合。 |
WPD_COMMAND_OBJECT_PROPERTIES_DELETE | OnDeleteProperties | 删除由给定属性键标识的属性。 |
设置和检索属性时使用访问作用域
WpdServiceSampleDriver 的六个属性处理程序中的代码与 WpdHelloWorld 驱动程序中的代码几乎完全相同。 例外情况是服务级别访问范围,这是第 7 部分的新Windows概念。
服务级别访问范围允许驱动程序将枚举限制为仅在给定父服务下找到的对象。 如果驱动程序支持访问范围,并且应用程序通过传递给定服务) 的 即插即用 标识符来调用 IPortableDeviceService::Open 方法 (,则应用程序只能访问设备、给定服务和该服务的子对象。 访问范围实现可能因驱动程序而异。 WpdServiceSampleDriver 通过使用位掩码定义两个基本范围级别、设备级 (限制较少的) 和限制更严格的服务级别 (来演示此) 。 下面的代码示例演示了这些级别的区别:
// Access Scope is a bit mask, where each bit enables access to a particular scope
// for example, contacts service is bit 1.
// The next scope, if any, will be in bit 2
// Full device access is a combination of all, requires all bits to be set
typedef enum tagACCESS_SCOPE
{
CONTACTS_SERVICE_ACCESS = 1,
FULL_DEVICE_ACCESS = 0xFFFFFFFF
}ACCESS_SCOPE;
当驱动程序使用 fake 对象填充枚举树时,每个内容对象的 FakeContent::RequiredScope 成员会使用适当的范围进行初始化。 例如,可以将 Contacts 对象初始化为仅限于联系人服务级别访问。
class FakeContactContent : public FakeContent
{
public:
FakeContactContent()
{
Format = WPD_OBJECT_FORMAT_ABSTRACT_CONTACT;
ContentType = WPD_CONTENT_TYPE_CONTACT;
RequiredScope = CONTACTS_SERVICE_ACCESS;
...
}
...
}
OnGetSupportedProperties 处理程序函数中的以下代码示例演示如何使用访问范围来确保返回正确的属性键:
// Add supported property keys for the specified object to the collection
if (hr == S_OK)
{
ACCESS_SCOPE Scope = m_pDevice->GetAccessScope(pParams);
hr = m_pDevice->GetSupportedProperties(Scope, wszObjectID, pKeys);
CHECK_HR(hr, "Failed to add supported property keys for object '%ws'", wszObjectID);
}
上一示例中的代码调用 FakeDevice::GetSupportedProperties 方法,该方法位于 FakeDevice.cpp 文件中。
HRESULT FakeDevice::GetSupportedProperties(
ACCESS_SCOPE Scope,
__in LPCWSTR wszObjectID,
__out IPortableDeviceKeyCollection* pKeys)
{
HRESULT hr = S_OK;
FakeContent* pContent = NULL;
if ((wszObjectID == NULL) ||
(pKeys == NULL))
{
hr = E_POINTER;
CHECK_HR(hr, "Cannot have NULL parameter");
return hr;
}
hr = GetContent(Scope, wszObjectID, &pContent);
CHECK_HR(hr, "Failed to get content '%ws'", wszObjectID);
if (hr == S_OK)
{
hr = pContent->GetSupportedProperties(pKeys);
CHECK_HR(hr, "Failed to get supported properties for '%ws'", wszObjectID);
}
return hr;
}
此方法首先尝试检索给定对象的内容。 然后,如果方法能够检索内容,它将检索请求的属性键。FakeContent::GetContent 检查范围,如果应用程序提供限制较少的访问范围 (例如设备范围的访问范围,则拒绝) 。
HRESULT FakeContent::GetContent(
ACCESS_SCOPE Scope,
__in LPCWSTR wszObjectID,
__out FakeContent** ppContent)
{
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
if (CanAccess(Scope))
{
// Within access scope, proceed . . .
}
else
{
hr = E_ACCESSDENIED;
CHECK_HR(hr, "GetContent: '%ws' was found but falls outside scope", wszObjectID);
}
return hr;
}
bool FakeContent::CanAccess(
ACCESS_SCOPE Scope)
{
return ((Scope & RequiredScope) == RequiredScope);
}