How the Application Creates the WIA Device
When an application intends to use a WIA device driver, it calls the IWiaDevMgr::CreateDevice method (described in the Microsoft Windows SDK documentation). The WIA service first calls IStiUSD::LockDevice to lock the WIA driver for mutually exclusive access. Next, the WIA service calls IWiaMiniDrv::drvInitializeWia to create the initial WIA item tree structure. Finally, the WIA service unlocks the device driver by calling IStiUSD::UnLockDevice.
The IWiaMiniDrv::drvInitializeWia method should perform the following tasks.
Cache the interface that the pStiDevice parameter points to for proper device locking. (For more information, see IWiaMiniDrv::drvLockWiaDevice.)
Create the initial WIA item tree structure.
Increment the current application connection count. This count is used to inform the driver whether an application is still connected. It also helps determine the proper action to take in IWiaMiniDrv::drvUnInitializeWia.
WIA items should be named with some logical meaning. Microsoft requires the following item names for Windows XP and later.
Root
This is the term for the root item of the WIA item tree.
Flatbed
This is the term for a scanner that supports a flatbed scanner only, or a scanner that supports a flatbed scanner with a document feeder.
Feeder
This is the term for a scanner that supports only a feeder.
The WIA service calls the IWiaMiniDrv::drvInitializeWia method in response to a WIA application's call to IWiaDevMgr::CreateDevice (described in the Windows SDK documentation). A consequence of this is that the WIA service calls the IWiaMiniDrv::drvInitializeWia method for each new client connection.
The IWiaMiniDrv::drvInitializeWia method should initialize any private structures and create the driver item tree. The driver item tree shows the layout of all WIA items supported by this WIA device. This method is used to create the initial tree structure only, not the contents (WIA properties). The WIA service will individually populate the WIA properties for the WIA driver items by making multiple calls to the IWiaMiniDrv::drvInitItemProperties method.
All WIA devices have a root item, which is the parent to all WIA device items. To create a WIA device item the WIA driver should call the WIA service helper function, wiasCreateDrvItem.
The following example shows how to create a WIA device root item.
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
//
}
To create a WIA child item, located directly under the root item created in the previous example, use code similar to the following.
Note **** Notice that the IWiaDrvItem::AddItemToFolder method is called to add the newly created child item to the root item.
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;
}
The following example shows an implementation of the IWiaMiniDrv::drvInitializeWia method.
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;
}