アプリケーションで 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 項目には、論理的な意味を持つ名前を付けてください。 Microsoft では、Windows XP 以降で次の項目名が必要です。
Root
これは、WIA 項目ツリーのルート項目の用語です。
Flatbed
これは、フラットベッド スキャナーのみに対応するスキャナー、またはドキュメント フィーダーを備えたフラットベッド スキャナーに対応するスキャナーの用語です。
Feeder
これは、フィーダーのみに対応するスキャナーの用語です。
WIA サービスは、WIA アプリケーションによる IWiaDevMgr::CreateDevice の呼び出し (Windows SDK ドキュメントで説明) に応答し、IWiaMiniDrv::d rvInitializeWia メソッドを呼び出します。 その結果、WIA サービスは、新しいクライアント接続ごとに IWiaMiniDrv::d rvInitializeWia メソッドを呼び出します。
IWiaMiniDrv::d rvInitializeWia メソッドは、プライベート構造体を初期化し、ドライバー項目ツリーを作成する必要があります。 ドライバー項目ツリーには、この WIA デバイスが対応しているすべての WIA 項目のレイアウトが表示されます。 このメソッドは、コンテンツ (WIA プロパティ) ではなく、初期ツリー構造のみを作成するために使用されます。 WIA サービスは、IWiaMiniDrv::d rvInitItemProperties メソッドを複数呼び出すことによって、WIA ドライバー項目の WIA プロパティを個別に設定します。
すべての 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;
}
次のコード例は、ValidateAndCacheConnectionInfo メソッドの実装を示しています。
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;
}