龙渊幻想-异世界冒险活动站

龙渊幻想-异世界冒险活动站

加载和卸载 WIA 微型驱动程序 - Windows drivers

安装 WIA 设备驱动程序后,WIA 服务会首次尝试加载它。 调用 WIA 微型驱动程序的 IStiUSD::Initialize 方法,应执行以下任务:

检查传输模式以确定调用方初始化此设备驱动程序的意向。 这是通过调用 IStiDeviceControl::GetMyDeviceOpenMode 方法完成的。

获取已安装设备的端口名称,以便此驱动程序可以在正确的端口上调用 CreateFile (Microsoft Windows SDK 中记录),以访问设备。 这是通过调用 IStiDeviceControl::GetMyDevicePortName 方法完成的。

读取设备安装期间写入的设备特定的注册表设置。 这可以通过使用传递给 IStiUSD::Initialize 的 hParametersKey 参数来完成。

首次加载驱动程序时,WIA 服务将调用 IStiUSD::Initialize 方法。 客户端使用旧 STI DDI 并调用 IStillImage::CreateDevice 方法时,也会调用 IStiUSD::Initialize 方法。

IStiUSD::Initialize 方法应初始化 WIA 驱动程序和设备以供使用。 如果 WIA 驱动程序稍后需要,WIA 驱动程序可以存储 IStiDeviceControl 接口指针。 在存储此接口之前,必须调用 IStiDeviceControl::AddRef 方法。 如果不需要存储接口,则忽略它。 如果尚未先调用 IStiDeviceControl::AddRef,请不要释放 IStiDeviceControl 接口。 这可能会导致不可预知的结果。 需要 IStiDeviceControl COM 接口 才能获取有关设备端口的信息。 可以通过调用 IStiDeviceControl::GetMyDevicePortName 方法获取对 CreateFile 函数的调用中使用的端口名称。 对于共享端口上的设备(例如串行端口设备),不建议在 IStiUSD::Initialize 中打开端口。 端口应仅在对 IStiUSD::LockDevice 的调用中打开。 应在内部控制端口关闭以提供快速访问。 (在 IStiUSD::LockDevice 和 IStiUSD::UnLockDevice 中打开和关闭是非常低效的。 CreateFile 可能会导致延迟,使设备对用户显示缓慢且无响应。

如果 WIA 驱动程序不能在同一设备端口上支持多个 CreateFile 调用,则应调用 IStiDeviceControl::GetMyDeviceOpenMode 方法。

WIA 驱动程序应检查返回的STI_DEVICE_CREATE_DATA标志模式值,并相应地打开端口。

如果必须打开设备端口,则应使用 对 CreateFile 的 调用。 打开端口时,应使用FILE_FLAG_OVERLAPPED标志。 这允许访问设备时使用 OVERLAPPED 结构(在 Windows SDK 文档中介绍)。 使用重叠的 I/O 有助于控制对硬件的响应式访问。 检测到问题后,WIA 驱动程序可以调用 CancelIo (Windows SDK 文档中所述)以停止所有当前硬件访问。

以下示例演示 IStiUSD::Initialize 方法的实现。

STDMETHODIMP CWIADevice::Initialize(

PSTIDEVICECONTROL pIStiDeviceControl,

DWORD dwStiVersion,

HKEY hParametersKey)

{

if (!pIStiDeviceControl) {

return STIERR_INVALID_PARAM;

}

HRESULT hr = S_OK;

//

// Get the mode of the device to check why we were created. status, data, or both...

//

DWORD dwMode = 0;

hr = pIStiDeviceControl->GetMyDeviceOpenMode(&dwMode);

if(FAILED(hr)){

return hr;

}

if(dwMode & STI_DEVICE_CREATE_DATA)

{

//

// device is being opened for data

//

}

if(dwMode & STI_DEVICE_CREATE_STATUS)

{

//

// device is being opened for status

//

}

if(dwMode & STI_DEVICE_CREATE_BOTH)

{

//

// device is being opened for both data and status

//

}

//

// Get the name of the device port to be used in a call to CreateFile().

//

WCHAR szDevicePortNameW[MAX_PATH];

memset(szDevicePortNameW,0,sizeof(szDevicePortNameW));

hr = pIStiDeviceControl->GetMyDevicePortName(szDevicePortNameW,

sizeof(szDevicePortNameW)/sizeof(WCHAR));

if(FAILED(hr)) {

return hr;

}

//

// Open kernel-mode device driver. Use the FILE_FLAG_OVERLAPPED flag

// for proper cancellation

// of kernel-mode operations and asynchronous file IO.

// The CancelIo() call will function properly if this flag is used.

// It is recommended to use this flag.

//

m_hDeviceDataHandle = CreateFileW(szDevicePortNameW,

GENERIC_READ | GENERIC_WRITE, // Access mask

0, // Share mode

NULL, // SA

OPEN_EXISTING, // Create disposition

FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,

NULL );

m_dwLastOperationError = ::GetLastError();

hr = (m_hDeviceDataHandle != INVALID_HANDLE_VALUE) ?

S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,m_dwLastOperationError);

if (FAILED(hr)) {

return hr;

}

//

// Open DeviceData section to read driver specific information

//

HKEY hKey = hParametersKey;

HKEY hOpenKey = NULL;

if (RegOpenKeyEx(hKey, // handle to open key

TEXT("DeviceData"), // address of name of subkey to open

0, // options (must be NULL)

KEY_QUERY_VALUE|KEY_READ, // just want to QUERY a value

&hOpenKey // address of handle to open key

) == ERROR_SUCCESS) {

//

// This is where you read registry entries for your device.

// The DeviceData section is the proper place to put this

// information. Information about your device should

// have been written using the WIA device's .INF installation

// file.

// You can access this information from this location in the

// Registry. The WIA service owns the hParameters HKEY.

// DO NOT CLOSE THIS KEY. Always close any HKEYS opened by

// this WIA driver after you are finished.

//

//

// close registry key when finished, reading DeviceData information.

//

RegCloseKey(hOpenKey);

} else {

return E_FAIL;

}

return hr;

}

WIA 服务在成功调用 IStiUSD::Initialize 方法后调用 IStiUSD::GetCapabilities。 然后,IStiUSD::GetCapabilities 提供 STI_USD_CAPS 结构,其中包含 STI 版本信息、WIA 支持标志(指示驱动程序功能的位标志)和任何事件要求。

以下示例演示 IStiUSD::GetCapabilities 的实现。

/********************************************************************\

* CWIADevice::GetCapabilities

* Remarks:

* This WIA driver sets the following capability flags:

* 1. STI_GENCAP_WIA - This driver supports WIA

* 2. STI_USD_GENCAP_NATIVE_PUSHSUPPORT - This driver supports push

* buttons

* 3. STI_GENCAP_NOTIFICATIONS - This driver requires the use of

* interrupt events.

*

\********************************************************************/

STDMETHODIMP CWIADevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)

{

//

// If the caller did not pass in the correct parameters,

// then fail the call with E_INVALIDARG.

//

if (!pUsdCaps) {

return E_INVALIDARG;

}

memset(pUsdCaps, 0, sizeof(STI_USD_CAPS));

pUsdCaps->dwVersion = STI_VERSION; // STI version

pUsdCaps->dwGenericCaps = STI_GENCAP_WIA| // WIA support

STI_USD_GENCAP_NATIVE_PUSHSUPPORT| // button support

STI_GENCAP_NOTIFICATIONS; // interrupt event support

return S_OK;

}