Как приложение создает устройство WIA
Когда приложение намерено использовать драйвер устройства WIA, оно вызывает метод IWiaDevMgr::CreateDevice (описан в документации по Microsoft Windows SDK). Служба WIA сначала вызывает IStiUSD::LockDevice , чтобы заблокировать драйвер WIA для взаимоисключающего доступа. Затем служба WIA вызывает IWiaMiniDrv::d rvInitializeWia для создания исходной структуры дерева элементов WIA. Наконец, служба WIA разблокирует драйвер устройства, вызывая IStiUSD::UnLockDevice.
Метод IWiaMiniDrv::d rvInitializeWia должен выполнять следующие задачи.
Кэшируйте интерфейс, на который указывает параметр pStiDevice для правильной блокировки устройства. (Дополнительные сведения см. в разделе IWiaMiniDrv::d rvLockWiaDevice.)
Создайте начальную структуру дерева элементов WIA.
Увеличьте текущее число подключений к приложению. Это число используется для информирования драйвера о том, подключено ли приложение по-прежнему. Он также помогает определить правильное действие в IWiaMiniDrv::d rvUnInitializeWia.
Элементы WIA должны называться с некоторым логическим значением. Корпорации Майкрософт требуются следующие имена элементов для Windows XP и более поздних версий.
Корневой
Это термин для корневого элемента дерева элементов WIA.
Планшетный
Это термин для сканера, который поддерживает только планшетный сканер, или сканер, поддерживающий планшетный сканер с подающий документ.
Подачи
Это термин для сканера, который поддерживает только подающий.
Служба WIA вызывает метод IWiaMiniDrv::d rvInitializeWia в ответ на вызов приложения WIA к IWiaDevMgr::CreateDevice (описано в документации windows SDK). Следствием этого является то, что служба WIA вызывает метод IWiaMiniDrv::d rvInitializeWia для каждого нового клиентского подключения.
Метод IWiaMiniDrv::d rvInitializeWia должен инициализировать любые частные структуры и создать дерево элементов драйвера. В дереве элементов драйвера отображается макет всех элементов WIA, поддерживаемых этим устройством WIA. Этот метод используется для создания только начальной древовидной структуры, а не содержимого (свойств WIA). Служба WIA по отдельности заполняет свойства WIA для элементов драйвера WIA, выполняя несколько вызовов метода IWiaMiniDrv::d rvInitItemProperties .
Все устройства WIA имеют корневой элемент, который является родительским для всех элементов устройств WIA. Чтобы создать элемент устройства WIA, драйвер WIA должен вызвать вспомогательную функцию службы WIA wiasCreateDrvItem.
В следующем примере показано, как создать корневой элемент устройства WIA.
LONG lItemFlags = WiaItemTypeFolder|WiaItemTypeDevice|WiaItemTypeRoot;
IWiaDrvItem *pIWiaDrvRootItem = NULL;
HRESULT hr =
wiasCreateDrvItem(
lItemFlags, // item flags
bstrRootItemName, // item name ("Root")
bstrRootFullItemName, // item full name ("0000\Root")
(IWiaMiniDrv *)this, // this WIA driver object
sizeof(MINIDRIVERITEMCONTEXT), // size of context
NULL, // context
&pIWiaDrvRootItem // created ROOT item
); // (IWiaDrvItem interface)
if(S_OK == hr){
//
// ROOT item was created successfully
//
}
Чтобы создать дочерний элемент WIA, расположенный непосредственно под корневым элементом, созданным в предыдущем примере, используйте код, аналогичный приведенному ниже.
Примечание *** Обратите внимание, что вызывается метод IWiaDrvItem::AddItemToFolder для добавления созданного дочернего элемента в корневой элемент.
LONG lItemFlags = WiaItemTypeFile|WiaItemTypeDevice|WiaItemTypeImage;
PMINIDRIVERITEMCONTEXT pItemContext = NULL;
IWiaDrvItem *pIWiaDrvNewItem = NULL;
HRESULT hr =
wiasCreateDrvItem(
lItemFlags, // item flags
bstrItemName, // item name ("Flatbed")
bstrFullItemName, // item full name ("0000\Root\Flatbed")
(IWiaMiniDrv *)this, // this WIA driver object
sizeof(MINIDRIVERITEMCONTEXT), // size of context
(PBYTE)&pItemContext, // context
&pIWiaDrvNewItem // created child item
); // (IWiaDrvItem interface)
if(S_OK == hr){
//
// A New WIA driver item was created successfully
//
hr = pIWiaDrvNewItem->AddItemToFolder(pIWiaDrvRootItem); // add the new item to the ROOT
if(S_OK == hr){
//
// successfully created and added a new WIA driver item to
// the WIA driver item tree.
//
}
pNewItem->Release();
pNewItem = NULL;
}
В следующем примере показана реализация метода IWiaMiniDrv::d rvInitializeWia .
HRESULT _stdcall CWIADevice::drvInitializeWia(
BYTE *pWiasContext,
LONG lFlags,
BSTR bstrDeviceID,
BSTR bstrRootFullItemName,
IUnknown *pStiDevice,
IUnknown *pIUnknownOuter,
IWiaDrvItem **ppIDrvItemRoot,
IUnknown **ppIUnknownInner,
LONG *plDevErrVal)
{
//
// If the caller did not pass in the correct parameters,
// then fail the call with E_INVALIDARG.
//
if (!pWiasContext) {
return E_INVALIDARG;
}
if (!plDevErrVal) {
return E_INVALIDARG;
}
HRESULT hr = S_OK;
*plDevErrVal = 0;
*ppIDrvItemRoot = NULL;
*ppIUnknownInner = NULL;
if (m_pStiDevice == NULL) {
//
// save STI device interface for locking
//
m_pStiDevice = (IStiDevice *)pStiDevice;
}
//
// build WIA item tree
//
LONG lItemFlags = WiaItemTypeFolder|WiaItemTypeDevice|WiaItemTypeRoot;
IWiaDrvItem *pIWiaDrvRootItem = NULL;
//
// create the ROOT item of the WIA device. This name should NOT be
// localized in different languages. "Root" is used by WIA drivers.
//
BSTR bstrRootItemName = SysAllocString(WIA_DEVICE_ROOT_NAME);
if(!bstrRootItemName) {
return E_OUTOFMEMORY;
}
hr = wiasCreateDrvItem(lItemFlags, // item flags
bstrRootItemName, // item name ("Root")
bstrRootFullItemName, // item full name ("0000\Root")
(IWiaMiniDrv *)this, // this WIA driver object
sizeof(MINIDRIVERITEMCONTEXT), // size of context
NULL, // context
&pIWiaDrvRootItem); // created ROOT item
// (IWiaDrvItem interface)
if (S_OK == hr) {
//
// ROOT item was created successfully, save the newly created Root
// item in the pointer given by the WIA service (ppIDrvItemRoot).
//
*ppIDrvItemRoot = pIWiaDrvRootItem;
//
// Create a child item directly under the Root WIA item
//
lItemFlags = WiaItemTypeFile|WiaItemTypeDevice|WiaItemTypeImage;
PMINIDRIVERITEMCONTEXT pItemContext = NULL;
IWiaDrvItem *pIWiaDrvNewItem = NULL;
//
// create a name for the WIA child item. "Flatbed" is used by
// WIA drivers that support a flatbed scanner.
//
BSTR bstrItemName = SysAllocString(WIA_DEVICE_FLATBED_NAME);
if (bstrItemName) {
WCHAR wszFullItemName[MAX_PATH + 1] = {0};
_snwprintf(wszFullItemName,(sizeof(wszFullItemName) / sizeof(WCHAR)) - 1,L"%ls\\%ls",
bstrRootFullItemName,bstrItemName);
BSTR bstrFullItemName = SysAllocString(wszFullItemName);
if (bstrFullItemName) {
hr = wiasCreateDrvItem(lItemFlags, // item flags
bstrItemName, // item name ("Flatbed")
trFullItemName, // item full name ("0000\Root\Flatbed")
(IWiaMiniDrv *)this, // this WIA driver object
sizeof(MINIDRIVERITEMCONTEXT), // size of context
(BYTE**)&pItemContext, // context
&pIWiaDrvNewItem); // created child item
// (IWiaDrvItem interface)
if (S_OK == hr) {
//
// A New WIA driver item was created successfully
//
hr = pIWiaDrvNewItem->AddItemToFolder(pIWiaDrvRootItem); // add the new item to the ROOT
if (S_OK == hr) {
//
// successfully created and added a new WIA
// driver item to the WIA driver item tree.
//
}
//
// The new item is no longer needed, because it has
// been passed to the WIA service.
//
pIWiaDrvNewItem->Release();
pIWiaDrvNewItem = NULL;
}
SysFreeString(bstrFullItemName);
bstrFullItemName = NULL;
} else {
hr = E_OUTOFMEMORY;
}
SysFreeString(bstrItemName);
bstrItemName = NULL;
} else {
hr = E_OUTOFMEMORY;
}
}
//
// increment application connection count
//
if(S_OK == hr){
InterlockedIncrement(&m_lClientsConnected);
}
return hr;
}