You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2507 lines
63 KiB
2507 lines
63 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1998
|
|
*
|
|
* TITLE: IItem.Cpp
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: ReedB
|
|
*
|
|
* DATE: 30 July, 1998
|
|
*
|
|
* DESCRIPTION:
|
|
* Implementation of CWiaItem for WIA scanner class driver.
|
|
*
|
|
*******************************************************************************/
|
|
#include "precomp.h"
|
|
#include "stiexe.h"
|
|
|
|
#define WIA_DECLARE_DEVINFO_PROP_ARRAY
|
|
#include "wiamindr.h"
|
|
#include "wiapsc.h"
|
|
#define WIA_DECLARE_MANAGED_PROPS
|
|
#include "helpers.h"
|
|
|
|
|
|
#include "wiapropp.h"
|
|
#include "ienumdc.h"
|
|
#include "ienumitm.h"
|
|
#include "callback.h"
|
|
#include "devmgr.h"
|
|
#include "wiaevntp.h"
|
|
|
|
/**************************************************************************\
|
|
* CopyDrvItemToTreeItem
|
|
*
|
|
* Create a CWiaTree object using a CWiaDrvItem as a template.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags -
|
|
* pCWiaDrvItemSrc -
|
|
* ppCWiaTreeDst -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CopyDrvItemToTreeItem(
|
|
LONG lFlags,
|
|
CWiaDrvItem *pCWiaDrvItemSrc,
|
|
CWiaItem *pCWiaItem,
|
|
CWiaTree **ppCWiaTreeDst)
|
|
{
|
|
DBG_FN(::CopyDrvItemToTreeItem);
|
|
HRESULT hr;
|
|
|
|
*ppCWiaTreeDst = NULL;
|
|
|
|
CWiaTree *pNewTreeItem = new CWiaTree;
|
|
|
|
if (pNewTreeItem) {
|
|
|
|
BSTR bstrItemName;
|
|
|
|
hr = pCWiaDrvItemSrc->GetItemName(&bstrItemName);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
BSTR bstrFullItemName;
|
|
|
|
hr = pCWiaDrvItemSrc->GetFullItemName(&bstrFullItemName);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = pNewTreeItem->Initialize(lFlags,
|
|
bstrItemName,
|
|
bstrFullItemName,
|
|
(void*)pCWiaItem);
|
|
if (SUCCEEDED(hr)) {
|
|
*ppCWiaTreeDst = pNewTreeItem;
|
|
}
|
|
|
|
SysFreeString(bstrFullItemName);
|
|
}
|
|
SysFreeString(bstrItemName);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
delete pNewTreeItem;
|
|
}
|
|
}
|
|
else {
|
|
DBG_ERR(("CopyDrvItemToTreeItem, new CWiaTree failed"));
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* UpdateWiaItemTree
|
|
*
|
|
* Update the application item tree. Called on the
|
|
* parent of the new child item or item to unlink.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlag - Action to preform.
|
|
* pWiaDrvItem -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::UpdateWiaItemTree(
|
|
LONG lFlag,
|
|
CWiaDrvItem *pWiaDrvItem)
|
|
{
|
|
DBG_FN(CWiaItem::UpdateWiaItemTree);
|
|
HRESULT hr = S_OK;
|
|
|
|
if (lFlag == DELETE_ITEM) {
|
|
|
|
//
|
|
// Unlink the item from the app item tree.
|
|
//
|
|
|
|
hr = m_pCWiaTree->RemoveItemFromFolder(WiaItemTypeDeleted);
|
|
}
|
|
else if (lFlag == ADD_ITEM) {
|
|
|
|
//
|
|
// Create a CWiaItem for this driver item.
|
|
//
|
|
|
|
CWiaItem *pItem = new CWiaItem();
|
|
|
|
if (!pItem) {
|
|
DBG_ERR(("UpdateWiaItemTree new CWiaItem failed"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pItem->Initialize(m_pIWiaItemRoot, NULL, m_pActiveDevice, pWiaDrvItem);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Create a CWiaTree object for this node and add it to the tree.
|
|
//
|
|
|
|
LONG lFlags;
|
|
|
|
pWiaDrvItem->GetItemFlags(&lFlags);
|
|
|
|
hr = CopyDrvItemToTreeItem(lFlags,
|
|
pWiaDrvItem,
|
|
pItem,
|
|
&pItem->m_pCWiaTree);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = pItem->m_pCWiaTree->AddItemToFolder(m_pCWiaTree);
|
|
if (SUCCEEDED(hr)) {
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
delete pItem;
|
|
}
|
|
else {
|
|
DBG_ERR(("UpdateWiaItemTree unknown flag: 0x%08X", lFlag));
|
|
hr = E_FAIL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildWiaItemTreeHelper
|
|
*
|
|
* Process the child items for BuildWiaItemTree.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pWiaDrvItem -
|
|
* pTreeParent -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::BuildWiaItemTreeHelper(
|
|
CWiaDrvItem *pWiaDrvItem,
|
|
CWiaTree *pTreeParent)
|
|
{
|
|
DBG_FN(CWiaItem::BuildWiaItemTreeHelper);
|
|
//
|
|
// Walk the child items.
|
|
//
|
|
|
|
CWiaDrvItem *pChildDrvItem;
|
|
|
|
HRESULT hr = pWiaDrvItem->GetFirstChildItem((IWiaDrvItem**) &pChildDrvItem);
|
|
|
|
while (hr == S_OK) {
|
|
|
|
//
|
|
// Create a CWiaItem for this node.
|
|
//
|
|
|
|
CWiaItem *pItem = new CWiaItem();
|
|
|
|
if (!pItem) {
|
|
DBG_ERR(("BuildWiaItemTreeHelper new CWiaItem failed"));
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
hr = pItem->Initialize(m_pIWiaItemRoot, NULL, m_pActiveDevice, pChildDrvItem);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Create a CWiaTree object for this node and add it to the tree.
|
|
//
|
|
|
|
LONG lFlags;
|
|
|
|
pChildDrvItem->GetItemFlags(&lFlags);
|
|
|
|
hr = CopyDrvItemToTreeItem(lFlags,
|
|
pChildDrvItem,
|
|
pItem,
|
|
&pItem->m_pCWiaTree);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = pItem->m_pCWiaTree->AddItemToFolder(pTreeParent);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
if (lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
|
|
|
|
//
|
|
// For folder items call BuildWiaItemTreeHelper recursively
|
|
// to process the folders child items.
|
|
//
|
|
|
|
hr = BuildWiaItemTreeHelper((CWiaDrvItem*)pChildDrvItem,
|
|
pItem->m_pCWiaTree);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Process the next sibling driver item.
|
|
//
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = pChildDrvItem->GetNextSiblingItem((IWiaDrvItem**) &pChildDrvItem);
|
|
}
|
|
}
|
|
else {
|
|
delete pItem;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Change S_FALSE to S_OK since S_FALSE simply means there are no more children to process.
|
|
//
|
|
|
|
if (hr == S_FALSE) {
|
|
hr = S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* BuildWiaItemTree
|
|
*
|
|
* For root items, build a copy of the driver item tree and create a
|
|
* CWiaItem for each node.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pIWiaItemRoot -
|
|
* pIWiaMiniDrv -
|
|
* pWiaDrvItem -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::BuildWiaItemTree(IWiaPropertyStorage *pIWiaDevInfoProps)
|
|
{
|
|
DBG_FN(CWiaItem::BuildWiaItemTree);
|
|
|
|
//
|
|
// Must be root item.
|
|
//
|
|
|
|
LONG lFlags;
|
|
|
|
m_pWiaDrvItem->GetItemFlags(&lFlags);
|
|
|
|
if (!(lFlags & WiaItemTypeRoot)) {
|
|
DBG_ERR(("BuildWiaItemTree, caller doesn't have WiaItemTypeRoot set"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = CopyDrvItemToTreeItem(lFlags, m_pWiaDrvItem, this, &m_pCWiaTree);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Since this is the root item, initialize the root item properties with a
|
|
// mirror of the DEVINFOPROPS (WIA_DIP_* ID's).
|
|
//
|
|
|
|
hr = InitRootProperties(pIWiaDevInfoProps);
|
|
if (FAILED(hr)) {
|
|
DBG_TRC(("BuildWiaItemTree, InitRootProperties, about to unlink..."));
|
|
UnlinkAppItemTree(WiaItemTypeDeleted);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Process the child items.
|
|
//
|
|
|
|
hr = BuildWiaItemTreeHelper(m_pWiaDrvItem,
|
|
m_pCWiaTree);
|
|
if (FAILED(hr)) {
|
|
DBG_TRC(("BuildWiaItemTree, BuildWiaItemTreeHelper failed, about to unlink..."));
|
|
UnlinkAppItemTree(WiaItemTypeDeleted);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* InitWiaManagedItemProperties
|
|
*
|
|
* A private helper for CWiaItem::Initialize, which initializes the
|
|
* WIA managed item properties based on the driver item values.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::InitWiaManagedItemProperties(
|
|
IWiaPropertyStorage *pIWiaDevInfoProps)
|
|
{
|
|
DBG_FN(CWiaItem::InitWiaManagedItemProperties);
|
|
ULONG ulNumProps;
|
|
|
|
ulNumProps = (m_pIWiaItemRoot == this) ? NUM_WIA_MANAGED_PROPS - 1 : NUM_WIA_MANAGED_PROPS;
|
|
//
|
|
// WIA manages the item name and type properties, so set the
|
|
// property names here.
|
|
//
|
|
|
|
HRESULT hr = wiasSetItemPropNames((BYTE*)this,
|
|
ulNumProps,
|
|
s_piItemNameType,
|
|
s_pszItemNameType);
|
|
|
|
//
|
|
// Set the name and type properties attributes.
|
|
//
|
|
|
|
PROPVARIANT pv;
|
|
ULONG ulFlag;
|
|
for (UINT i = 0; i < ulNumProps; i++) {
|
|
|
|
if (i == PROFILE_INDEX) {
|
|
pv.vt = VT_BSTR | VT_VECTOR;
|
|
ulFlag = WIA_PROP_RW | WIA_PROP_CACHEABLE | WIA_PROP_LIST;
|
|
} else {
|
|
pv.vt = VT_I4;
|
|
ulFlag = WIA_PROP_READ | WIA_PROP_CACHEABLE | WIA_PROP_NONE;
|
|
}
|
|
pv.ulVal = 0;
|
|
|
|
hr = wiasSetPropertyAttributes((BYTE*)this,
|
|
1,
|
|
&s_psItemNameType[i],
|
|
&ulFlag,
|
|
&pv);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Initialize, wiasSetPropertyAttributes failed, index: %d", i));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the item names and type from the driver item and set
|
|
// them to the item properties.
|
|
//
|
|
|
|
BSTR bstrItemName;
|
|
BSTR bstrFullItemName;
|
|
|
|
hr = m_pWiaDrvItem->GetItemName(&bstrItemName);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = m_pWiaDrvItem->GetFullItemName(&bstrFullItemName);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
LONG lFlags;
|
|
|
|
m_pWiaDrvItem->GetItemFlags(&lFlags); // Can't fail, except on param validate.
|
|
|
|
//
|
|
// Set the item names and type.
|
|
//
|
|
|
|
PROPVARIANT *propvar;
|
|
|
|
propvar = (PROPVARIANT*) LocalAlloc(LPTR, sizeof(PROPVARIANT) * ulNumProps);
|
|
if (propvar) {
|
|
memset(propvar, 0, sizeof(PROPVARIANT) * ulNumProps);
|
|
|
|
propvar[0].vt = VT_BSTR;
|
|
propvar[0].bstrVal = bstrItemName;
|
|
propvar[1].vt = VT_BSTR;
|
|
propvar[1].bstrVal = bstrFullItemName;
|
|
propvar[2].vt = VT_I4;
|
|
propvar[2].lVal = lFlags;
|
|
|
|
hr = (m_pPropStg->CurStg())->WriteMultiple(ulNumProps,
|
|
s_psItemNameType,
|
|
propvar,
|
|
WIA_DIP_FIRST);
|
|
if (SUCCEEDED(hr)) {
|
|
//
|
|
// Fill in ICM Profile information
|
|
//
|
|
|
|
hr = FillICMPropertyFromRegistry(pIWiaDevInfoProps, (IWiaItem*) this);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
ReportReadWriteMultipleError(hr, "CWiaItem::InitWiaManagedItemProperties",
|
|
NULL,
|
|
FALSE,
|
|
ulNumProps,
|
|
s_psItemNameType);
|
|
}
|
|
LocalFree(propvar);
|
|
} else {
|
|
DBG_ERR(("CWiaItem::InitWiaManagedItemProperties, Out of Memory!"));
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
SysFreeString(bstrFullItemName);
|
|
|
|
}
|
|
SysFreeString(bstrItemName);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
*
|
|
* InitRootProperties
|
|
*
|
|
* A private helper for CWiaItem::Initialize, which initializes the
|
|
* root item properties to a mirror of DEVINFOPROPS.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* status
|
|
*
|
|
* History:
|
|
*
|
|
* 9/3/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::InitRootProperties(IWiaPropertyStorage *pIWiaDevInfoProps)
|
|
{
|
|
DBG_FN(CWiaItem::InitRootProperties);
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// Write the root item property names.
|
|
//
|
|
|
|
hr = WriteItemPropNames(NUMROOTITEMPROPS, g_piRootItem, g_pszRootItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::InitRootProperties, WritePropNames failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Copy the device information properties from source to destination.
|
|
//
|
|
|
|
PROPVARIANT propvar[WIA_NUM_DIP];
|
|
ULONG ulIndex;
|
|
|
|
memset(propvar, 0, sizeof(propvar));
|
|
|
|
hr = pIWiaDevInfoProps->ReadMultiple(WIA_NUM_DIP,
|
|
g_psDeviceInfo,
|
|
propvar);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = (m_pPropStg->CurStg())->WriteMultiple(WIA_NUM_DIP,
|
|
g_psDeviceInfo,
|
|
propvar,
|
|
WIA_DIP_FIRST);
|
|
|
|
if (FAILED(hr)) {
|
|
ReportReadWriteMultipleError(hr, "InitRootProperties", NULL, FALSE, WIA_NUM_DIP, g_psDeviceInfo);
|
|
}
|
|
|
|
FreePropVariantArray(WIA_NUM_DIP, propvar);
|
|
}
|
|
else {
|
|
ReportReadWriteMultipleError(hr, "InitRootProperties", NULL, TRUE, WIA_NUM_DIP, g_psDeviceInfo);
|
|
DBG_ERR(("CWiaItem::InitRootProperties failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Write out the property info from our private array.
|
|
//
|
|
|
|
hr = wiasSetItemPropAttribs((BYTE*)this,
|
|
NUMROOTITEMPROPS,
|
|
g_psRootItem,
|
|
g_wpiRootItem);
|
|
if (SUCCEEDED(hr) && m_pActiveDevice->m_DrvWrapper.IsVolumeDevice()) {
|
|
//
|
|
// This is a volume device. We must add some volume specific properties
|
|
//
|
|
|
|
hr = AddVolumePropertiesToRoot(m_pActiveDevice);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* QueryInterface
|
|
* AddRef
|
|
* Release
|
|
*
|
|
* DESCRIPTION:
|
|
* IUnknown Interface. AddRef and Release mantain a global refernce count
|
|
* of all device objects on the root item.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::QueryInterface(const IID& iid, void** ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
if (iid == IID_IUnknown || iid == IID_IWiaItem) {
|
|
*ppv = (IWiaItem*) this;
|
|
} else if (iid == IID_IWiaPropertyStorage) {
|
|
*ppv = (IWiaPropertyStorage*) this;
|
|
} else if (iid == IID_IPropertyStorage) {
|
|
*ppv = (IPropertyStorage*) this;
|
|
} else if (iid == IID_IWiaDataTransfer) {
|
|
*ppv = (IWiaDataTransfer*) this;
|
|
} else if (iid == IID_IWiaItemInternal) {
|
|
*ppv = (IWiaItemInternal*) this;
|
|
} else if (iid == IID_IWiaItemExtras) {
|
|
*ppv = (IWiaItemExtras*) this;
|
|
} else {
|
|
|
|
//
|
|
// Blind aggregation to optional inner component.
|
|
//
|
|
|
|
if (m_pIUnknownInner) {
|
|
return m_pIUnknownInner->QueryInterface(iid, ppv);
|
|
}
|
|
else {
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
ULONG _stdcall CWiaItem::AddRef()
|
|
{
|
|
DBG_FN(CWiaItem::AddRef);
|
|
|
|
TAKE_ACTIVE_DEVICE tad(m_pActiveDevice);
|
|
|
|
LONG lType = 0;
|
|
LONG lRef = 1;
|
|
|
|
lRef = InterlockedIncrement((long*) &m_cLocalRef);
|
|
GetItemType(&lType);
|
|
if (!(lType & WiaItemTypeRemoved)) {
|
|
lRef = InterlockedIncrement((long*) &(((CWiaItem*)m_pIWiaItemRoot)->m_cRef));
|
|
}
|
|
|
|
return lRef;
|
|
}
|
|
|
|
ULONG _stdcall CWiaItem::Release()
|
|
{
|
|
DBG_FN(CWiaItem::Release);
|
|
|
|
LONG lType = 0;
|
|
ULONG ulRef = InterlockedDecrement((long*)&m_cLocalRef);
|
|
GetItemType(&lType);
|
|
if (lType & WiaItemTypeRemoved) {
|
|
|
|
if (ulRef == 0) {
|
|
delete this;
|
|
return 0;
|
|
} else {
|
|
return m_cLocalRef;
|
|
}
|
|
} else if (InterlockedDecrement((long*) &(((CWiaItem*)m_pIWiaItemRoot)->m_cRef)) == 0) {
|
|
|
|
ulRef = ((CWiaItem*)m_pIWiaItemRoot)->m_cRef;
|
|
|
|
//
|
|
// If the combined refernce count of the root item goes to zero
|
|
// first notify driver that client connection is being removed, then
|
|
// unlink the tree and release all of the items.
|
|
//
|
|
|
|
//
|
|
// But first cleanup any remote transfers in progress that are a
|
|
// result of crashed or malicious clients
|
|
//
|
|
CWiaItem * pItem = (CWiaItem*) m_pIWiaItemRoot;
|
|
while(pItem) {
|
|
CWiaRemoteTransfer *pTransfer =
|
|
(CWiaRemoteTransfer *)InterlockedExchangePointer((PVOID *)&pItem->m_pRemoteTransfer, NULL);
|
|
if(pTransfer) {
|
|
CleanupRemoteTransfer(pTransfer);
|
|
}
|
|
pItem = pItem->GetNextLinearItem();
|
|
}
|
|
|
|
HRESULT hr = E_FAIL;
|
|
LONG lDevErrVal = 0;
|
|
ACTIVE_DEVICE *pActiveDevice = m_pActiveDevice;
|
|
|
|
//
|
|
// Call drvUnInitialize if it hasn't been called yet (could have been
|
|
// called if driver was unloaded).
|
|
// Note that we must check flags on the ROOT item.
|
|
//
|
|
if (!(((CWiaItem*)m_pIWiaItemRoot)->m_lInternalFlags & ITEM_FLAG_DRV_UNINITIALIZE_THROWN)) {
|
|
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvUnInitializeWia((BYTE*)m_pIWiaItemRoot);
|
|
}
|
|
m_lInternalFlags |= ITEM_FLAG_DRV_UNINITIALIZE_THROWN;
|
|
}
|
|
}
|
|
|
|
DBG_TRC(("CWiaItem::Release, m_cRef = 0, about to unlink..."));
|
|
UnlinkAppItemTree(WiaItemTypeDeleted);
|
|
|
|
if (pActiveDevice) {
|
|
//
|
|
// Release the ACTIVE_DEVICE object. Notice that we release it AFTER
|
|
// the item is through with it.
|
|
//
|
|
|
|
pActiveDevice->Release();
|
|
pActiveDevice = NULL;
|
|
}
|
|
}
|
|
|
|
return ulRef;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::UnlinkChildAppItemTree
|
|
*
|
|
* This method recursively unlinks the tree by calling
|
|
* RemoveItemFromFolder on each item under the root.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lReason - Reason for unlink of tree.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/21/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::UnlinkChildAppItemTree(LONG lReason)
|
|
{
|
|
DBG_FN(CWiaItem::UnlinkChildAppItemTree);
|
|
|
|
//
|
|
// Check that we have a valid tree
|
|
//
|
|
|
|
if (!m_pCWiaTree) {
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// Delete the childern.
|
|
//
|
|
|
|
CWiaTree *pChild, *pNext;
|
|
|
|
HRESULT hr = m_pCWiaTree->GetFirstChildItem(&pChild);
|
|
|
|
while (hr == S_OK) {
|
|
|
|
//
|
|
// Get a tree items associated app item.
|
|
//
|
|
|
|
CWiaItem *pChildAppItem;
|
|
|
|
pChildAppItem = NULL;
|
|
hr = pChild->GetItemData((void**)&pChildAppItem);
|
|
if (hr == S_OK) {
|
|
//
|
|
// If the child is a folder then call
|
|
// recursively to delete all childern under.
|
|
//
|
|
|
|
LONG lFlags;
|
|
|
|
pChild->GetItemFlags(&lFlags);
|
|
|
|
if (lFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
|
|
hr = pChildAppItem->UnlinkChildAppItemTree(lReason);
|
|
if (FAILED(hr)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaItem::UnlinkChildAppItemTree no app item on tree item: %X", pChild));
|
|
}
|
|
|
|
hr = pChild->GetNextSiblingItem(&pNext);
|
|
|
|
//
|
|
// Remove item from tree.
|
|
//
|
|
|
|
pChild->RemoveItemFromFolder(lReason);
|
|
|
|
//
|
|
// Delete the child item.
|
|
//
|
|
|
|
if (pChildAppItem) {
|
|
|
|
delete pChildAppItem;
|
|
}
|
|
|
|
pChild = pNext;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::UnlinkAppItemTree
|
|
*
|
|
* This method unlinks the app item tree.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lReason - Reason for unlinking the tree.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/21/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::UnlinkAppItemTree(LONG lReason)
|
|
{
|
|
DBG_FN(CWiaItem::UnlinkAppItemTree);
|
|
|
|
//
|
|
// Work off of the root item.
|
|
//
|
|
|
|
CWiaItem *pRoot = (CWiaItem*) m_pIWiaItemRoot;
|
|
|
|
//
|
|
// Unlink any childern.
|
|
//
|
|
|
|
pRoot->UnlinkChildAppItemTree(lReason);
|
|
|
|
//
|
|
// Finally, delete the root item.
|
|
//
|
|
|
|
delete pRoot;
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::CWiaItem
|
|
*
|
|
* CWiaItem Constructor Method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaItem::CWiaItem()
|
|
{
|
|
m_ulSig = CWIAITEM_SIG;
|
|
m_cRef = 0;
|
|
m_cLocalRef = 0;
|
|
|
|
m_pWiaDrvItem = NULL;
|
|
m_pActiveDevice = NULL;
|
|
m_pIUnknownInner = NULL;
|
|
m_pCWiaTree = NULL;
|
|
m_pIWiaItemRoot = this;
|
|
m_bInitialized = FALSE;
|
|
m_pICMValues = NULL;
|
|
m_lICMSize = 0;
|
|
|
|
m_pPropStg = NULL;
|
|
|
|
m_hBandSection = NULL;
|
|
m_pBandBuffer = NULL;
|
|
m_lBandBufferLength = 0;
|
|
m_ClientBaseAddress = 0;
|
|
m_bMapSection = FALSE;
|
|
m_cwfiBandedTran = 0;
|
|
m_pwfiBandedTran = NULL;
|
|
m_pRemoteTransfer = NULL;
|
|
m_lLastDevErrVal = 0;
|
|
m_lInternalFlags = 0;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::Initialize
|
|
*
|
|
* CWiaItem Initialize method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pIWiaItemRoot -
|
|
* pIWiaMiniDrv -
|
|
* pWiaDrvItem -
|
|
* pIUnknownInner -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::Initialize(
|
|
IWiaItem *pIWiaItemRoot,
|
|
IWiaPropertyStorage *pIWiaDevInfoProps,
|
|
ACTIVE_DEVICE *pActiveDevice,
|
|
CWiaDrvItem *pWiaDrvItem,
|
|
IUnknown *pIUnknownInner)
|
|
{
|
|
DBG_FN(CWiaItem::Initialize);
|
|
#ifdef DEBUG
|
|
BSTR bstr;
|
|
if SUCCEEDED(pWiaDrvItem->GetItemName(&bstr)) {
|
|
DBG_TRC(("CWiaItem::Initialize: 0x%08X, %S, drv item: 0x%08X", this, bstr, pWiaDrvItem));
|
|
SysFreeString(bstr);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Validate parameters
|
|
//
|
|
|
|
if (!pActiveDevice || !pIWiaItemRoot || !pWiaDrvItem) {
|
|
DBG_ERR(("CWiaItem::Initialize NULL input parameters"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
//
|
|
// If optional inner component is present, save a pointer to it.
|
|
//
|
|
|
|
if (pIUnknownInner) {
|
|
DBG_TRC(("CWiaItem::Initialize, pIUnknownInner: %X", pIUnknownInner));
|
|
m_pIUnknownInner = pIUnknownInner;
|
|
}
|
|
|
|
//
|
|
// Link to the items corresponding driver item.
|
|
//
|
|
|
|
m_pWiaDrvItem = pWiaDrvItem;
|
|
m_pIWiaItemRoot = pIWiaItemRoot;
|
|
m_pActiveDevice = pActiveDevice;
|
|
m_pWiaDrvItem->SetActiveDevice(pActiveDevice);
|
|
|
|
HRESULT hr = pWiaDrvItem->LinkToDrvItem(this);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Initialize, LinkToDrvItem failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Create streams and property storage for item properties.
|
|
//
|
|
|
|
m_pPropStg = new CWiaPropStg();
|
|
if (m_pPropStg) {
|
|
hr = m_pPropStg->Initialize();
|
|
if (FAILED(hr)) {
|
|
delete m_pPropStg;
|
|
m_pPropStg = NULL;
|
|
DBG_ERR(("CWiaItem::Initialize, PropertyStorage Initialize failed"));
|
|
return hr;
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::Initialize, not enough memory to create CWiaPropStg"));
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize the WIA managed item properties (name, full name, type, ...)
|
|
// from the driver item. Must set m_bInitialized to TRUE so that
|
|
// InitWiaManagedProperties doesn't attempt to InitLazyProps()
|
|
//
|
|
|
|
m_bInitialized = TRUE;
|
|
hr = InitWiaManagedItemProperties(pIWiaDevInfoProps);
|
|
|
|
pWiaDrvItem->AddRef();
|
|
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Initialize, InitWiaManagedItemProperties failed"));
|
|
m_bInitialized = FALSE;
|
|
return hr;
|
|
}
|
|
//
|
|
// If this is the root item, build a copy of the driver item tree
|
|
// and create a CWiaItem for each node.
|
|
//
|
|
|
|
if (this == pIWiaItemRoot) {
|
|
hr = BuildWiaItemTree(pIWiaDevInfoProps);
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Initialize, BuildWiaItemTree failed"));
|
|
return hr;
|
|
}
|
|
|
|
m_bInitialized = FALSE;
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::InitLazyProps
|
|
*
|
|
* Helper used to implement lazy initialization. Property initialization
|
|
* is put off until the item is being accessed by an application for the
|
|
* first time.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* bLockDevice - bool value specifying whether a lock is needed.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 10/10/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::InitLazyProps(
|
|
BOOL bLockDevice)
|
|
{
|
|
DBG_FN(CWiaItem::InitLazyProps);
|
|
HRESULT hr = S_OK;
|
|
|
|
LONG lFlags = 0;
|
|
|
|
//
|
|
// Must set to TRUE before call to drvInitItemProperties
|
|
//
|
|
|
|
m_bInitialized = TRUE;
|
|
|
|
//
|
|
// Call the device to initialize the item properties.
|
|
//
|
|
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(bLockDevice, this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvInitItemProperties((BYTE*)this,lFlags, &m_lLastDevErrVal);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
m_bInitialized = FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::~CWiaItem
|
|
*
|
|
* CWiaItem Destructor Method.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaItem::~CWiaItem()
|
|
{
|
|
DBG_FN(CWiaItem::~CWiaItem);
|
|
#ifdef ITEM_TRACE
|
|
BSTR bstr;
|
|
|
|
if (m_pWiaDrvItem && SUCCEEDED(m_pWiaDrvItem->GetItemName(&bstr))) {
|
|
DBG_TRC(("CWiaItem destroy: %08X, %S", this, bstr));
|
|
SysFreeString(bstr);
|
|
}
|
|
else {
|
|
DBG_TRC(("CWiaItem destroy: %08X", this));
|
|
}
|
|
#endif
|
|
|
|
CWiaRemoteTransfer *pRemoteTransfer =
|
|
(CWiaRemoteTransfer *) InterlockedExchangePointer((PVOID *)&m_pRemoteTransfer, NULL);
|
|
|
|
if(pRemoteTransfer) {
|
|
CleanupRemoteTransfer(m_pRemoteTransfer);
|
|
}
|
|
|
|
//
|
|
// Delete the associated tree item.
|
|
//
|
|
|
|
if (m_pCWiaTree) {
|
|
delete m_pCWiaTree;
|
|
m_pCWiaTree = NULL;
|
|
}
|
|
|
|
//
|
|
// Release WiaDrvItem. If ref count of m_pWiaDrvItem goes to zero
|
|
// it will be destroyed at this time. For the ref count to be zero
|
|
// no other CWiaItem object may have reference to it and it must be
|
|
// disconnected from the device item tree.
|
|
//
|
|
|
|
if (m_pWiaDrvItem) {
|
|
|
|
//
|
|
// Unlink from the app item's corresponding driver item.
|
|
//
|
|
|
|
m_pWiaDrvItem->UnlinkFromDrvItem(this);
|
|
|
|
m_pWiaDrvItem->Release();
|
|
m_pWiaDrvItem = NULL;
|
|
}
|
|
|
|
//
|
|
// Free the item property storage and streams.
|
|
//
|
|
|
|
if (m_pPropStg) {
|
|
|
|
delete m_pPropStg;
|
|
m_pPropStg = NULL;
|
|
}
|
|
|
|
//
|
|
// Free the cached ICM values
|
|
//
|
|
|
|
if (m_pICMValues) {
|
|
LocalFree(m_pICMValues);
|
|
m_pICMValues = NULL;
|
|
}
|
|
|
|
//
|
|
// Set other members to empty since we're done with this item.
|
|
//
|
|
|
|
m_pWiaDrvItem = NULL;
|
|
m_pIUnknownInner = NULL;
|
|
m_pIWiaItemRoot = NULL;
|
|
m_bInitialized = FALSE;
|
|
m_lICMSize = 0;
|
|
|
|
|
|
m_hBandSection = NULL;
|
|
m_pBandBuffer = NULL;
|
|
m_lBandBufferLength = 0;
|
|
m_ClientBaseAddress = 0;
|
|
m_bMapSection = FALSE;
|
|
m_cwfiBandedTran = 0;
|
|
m_pwfiBandedTran = NULL;
|
|
m_lInternalFlags = 0;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetItemType
|
|
*
|
|
* Get the item type from the corresponding driver item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pItemType - Pointer to the returned item type.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::GetItemType(LONG *pItemType)
|
|
{
|
|
DBG_FN(CWiaItem::GetItemType);
|
|
LONG lFlags = 0;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if (m_pWiaDrvItem) {
|
|
|
|
//
|
|
// Get the driver item flags. This is the flags basis for App. Items
|
|
// that were created as a result of copying the driver item tree i.e.
|
|
// non-generated items.
|
|
//
|
|
|
|
hr = m_pWiaDrvItem->GetItemFlags(&lFlags);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// The App. item may have analysis-generated children, which the
|
|
// corresponding driver item wont have. So check whether this
|
|
// item has children, and adjust the flags accordingly.
|
|
//
|
|
|
|
if (m_pCWiaTree) {
|
|
if (m_pCWiaTree->GetFirstChildItem(NULL) == S_OK) {
|
|
|
|
//
|
|
// Has children, so clear File flag and set Folder
|
|
//
|
|
|
|
if (!(lFlags & WiaItemTypeHasAttachments))
|
|
{
|
|
lFlags = (lFlags | WiaItemTypeFolder) & ~WiaItemTypeFile;
|
|
}
|
|
}
|
|
}
|
|
|
|
*pItemType = lFlags;
|
|
} else {
|
|
DBG_ERR(("CWiaItem::GetItemType, Could not get the driver item flags!"));
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::EnumChildItems
|
|
*
|
|
* Enumerate all child items under the current item, providing the
|
|
* item is a folder
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ppIEnumWiaItem - return an IEnumWiaItem object to the caller
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::EnumChildItems(IEnumWiaItem **ppIEnumWiaItem)
|
|
{
|
|
DBG_FN(CWiaItem::EnumChildItems);
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumChildItems, ValidateWiaDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Validate parameters
|
|
//
|
|
|
|
if (ppIEnumWiaItem == NULL) {
|
|
DBG_ERR(("CWiaItem::EnumChildItems NULL input parameters"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
*ppIEnumWiaItem = NULL;
|
|
|
|
//
|
|
// Create the enumerator object.
|
|
//
|
|
|
|
CEnumWiaItem* pEnumWiaItem = new CEnumWiaItem();
|
|
|
|
if (pEnumWiaItem != NULL) {
|
|
|
|
//
|
|
// Initialize the enumerator object.
|
|
//
|
|
|
|
hr = pEnumWiaItem->Initialize(this);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// get IID_IEnumWiaItem Interface
|
|
//
|
|
|
|
hr = pEnumWiaItem->QueryInterface(IID_IEnumWiaItem, (void **)ppIEnumWiaItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumChildItems, QI of IID_IEnumWiaItem failed"));
|
|
delete pEnumWiaItem;
|
|
}
|
|
}
|
|
else {
|
|
delete pEnumWiaItem;
|
|
}
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaItem::EnumChildItems, new CEnumWiaItem failed"));
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
CWiaItem* _stdcall CWiaItem::GetNextLinearItem(void)
|
|
{
|
|
return m_pCWiaTree ?
|
|
m_pCWiaTree->GetNextLinearItem() : NULL;
|
|
}
|
|
|
|
CWiaItem* _stdcall CWiaTree::GetNextLinearItem()
|
|
{
|
|
if(m_pLinearList && m_pLinearList->m_pData) {
|
|
return static_cast<CWiaItem *>(m_pLinearList->m_pData);
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* DeleteItem
|
|
*
|
|
* Applications use this method to delete items.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DeleteItem(LONG lFlags)
|
|
{
|
|
DBG_FN(CWiaItem::DeleteItem);
|
|
LONG lItemFlags;
|
|
HRESULT hr;
|
|
IWiaDrvItem *pIChildItem = NULL;
|
|
LONG lAccessRights;
|
|
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::DeleteItem, ValidateWiaDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::DeleteItem, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
GetItemType(&lItemFlags);
|
|
|
|
//
|
|
// Root item can not be deleted, the application needs it
|
|
// in order to release the device.
|
|
//
|
|
|
|
if (lItemFlags & WiaItemTypeRoot) {
|
|
DBG_ERR(("CWiaItem::DeleteItem, Deletion was attempted on a Root Item"));
|
|
return (E_INVALIDARG);
|
|
}
|
|
|
|
//
|
|
// Folder can be deleted only when it is empty
|
|
//
|
|
|
|
if (lItemFlags & (WiaItemTypeFolder | WiaItemTypeHasAttachments)) {
|
|
|
|
if (m_pCWiaTree->GetFirstChildItem(NULL) == S_OK) {
|
|
DBG_ERR(("CWiaItem::DeleteItem, Item still has children!"));
|
|
return (E_INVALIDARG);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check whether the item can be deleted. Generated items can always be
|
|
// deleted regardless of AccessRights
|
|
//
|
|
|
|
hr = wiasReadPropLong((BYTE*)this, WIA_IPA_ACCESS_RIGHTS, &lAccessRights, NULL, false);
|
|
if (hr == S_OK) {
|
|
|
|
if (!((lAccessRights & WIA_ITEM_CAN_BE_DELETED) || (lItemFlags & WiaItemTypeGenerated))){
|
|
DBG_ERR(("CWiaItem::DeleteItem, Item can not be deleted"));
|
|
return (HRESULT_FROM_WIN32(ERROR_INVALID_ACCESS));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If it's not a generated item, call the driver and ask it to remove
|
|
// the item from it's tree.
|
|
//
|
|
|
|
if (!(lItemFlags & WiaItemTypeGenerated)) {
|
|
//
|
|
// Call the mini driver to delete the driver item.
|
|
//
|
|
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvDeleteItem((BYTE*)this, lFlags, &m_lLastDevErrVal);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Unlink the IWiaDrvItem from the device item tree.
|
|
// This will also disable any device access through m_pWiaDrvItem
|
|
// by setting the WiaItemTypeDeleted flag.
|
|
//
|
|
|
|
hr = m_pWiaDrvItem->RemoveItemFromFolder(WiaItemTypeDeleted | WiaItemTypeRemoved);
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Since there is no corresponding driver item, manually remove this
|
|
// from the tree,
|
|
//
|
|
|
|
hr = m_pCWiaTree->RemoveItemFromFolder(WiaItemTypeDeleted | WiaItemTypeRemoved);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Decrement the root item ref count by however much this local ref count
|
|
// contributed to it.
|
|
//
|
|
for (ULONG i = 0; i < m_cLocalRef; i++) {
|
|
m_pIWiaItemRoot->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* AnalyzeItem
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::AnalyzeItem(LONG lFlags)
|
|
{
|
|
DBG_FN(CWiaItem::AnalyzeItem);
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
HRESULT hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::AnalyzeItem, ValidateWiaDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::AnalyzeItem, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// call driver to implement this device dependent call
|
|
//
|
|
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvAnalyzeItem((BYTE*)this, lFlags, &m_lLastDevErrVal);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CreateChildItem
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::CreateChildItem(
|
|
LONG lFlags,
|
|
BSTR bstrItemName,
|
|
BSTR bstrFullItemName,
|
|
IWiaItem **ppNewItem)
|
|
{
|
|
DBG_FN(CWiaItem::CreateChildItem);
|
|
|
|
CGenWiaItem *pGenItem = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppNewItem = NULL;
|
|
|
|
//
|
|
// Create the new item
|
|
//
|
|
|
|
hr = wiasCreateChildAppItem((BYTE*) this,
|
|
lFlags,
|
|
bstrItemName,
|
|
bstrFullItemName,
|
|
(BYTE**) &pGenItem);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Get the driver to initialize the item.
|
|
//
|
|
|
|
hr = pGenItem->InitLazyProps(TRUE);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
//
|
|
// Return the IWiaItem interface to the calling App.
|
|
//
|
|
|
|
hr = pGenItem->QueryInterface(IID_IWiaItem,
|
|
(VOID**)ppNewItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::CreateChildItem, bad mini driver interface"));
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::CreateChildItem, Error initializing the item properties"));
|
|
}
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
delete pGenItem;
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::CreateChildItem, error creating generated item"));
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* DeviceCommand
|
|
*
|
|
* Issue a device command.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFlags -
|
|
* plCommand -
|
|
* ppIWiaItem -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 11/12/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DeviceCommand(
|
|
LONG lFlags,
|
|
const GUID *plCommand,
|
|
IWiaItem **ppIWiaItem)
|
|
{
|
|
DBG_FN(CWiaItem::DeviceCommand);
|
|
IWiaDrvItem *pIWiaDrvItem = NULL;
|
|
HRESULT hr;
|
|
CWiaItem *pItem;
|
|
|
|
//
|
|
// Driver interface must be valid.
|
|
//
|
|
|
|
if (!m_pActiveDevice) {
|
|
DBG_ERR(("CWiaItem::DeviceCommand, bad mini driver interface"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::DeviceCommand, ValidateWiaDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::DeviceCommand, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.WIA_drvDeviceCommand((BYTE*)this, lFlags, plCommand, &pIWiaDrvItem, &m_lLastDevErrVal);
|
|
}
|
|
}
|
|
|
|
if ((!pIWiaDrvItem) || (!ppIWiaItem)) {
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// If we are here, the command has resulted in a drv item being added to
|
|
// the drv and app item trees. Find and return the app item.
|
|
//
|
|
|
|
if (ppIWiaItem) {
|
|
|
|
BSTR bstrName;
|
|
|
|
*ppIWiaItem = NULL;
|
|
|
|
hr = pIWiaDrvItem->GetFullItemName(&bstrName);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = FindItemByName(0, bstrName, ppIWiaItem);
|
|
}
|
|
SysFreeString(bstrName);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* DeviceDlg
|
|
*
|
|
* DESCRIPTION:
|
|
* Executes only on the client side.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DeviceDlg(
|
|
HWND hwndParent,
|
|
LONG lFlags,
|
|
LONG lIntent,
|
|
LONG *plItemCount,
|
|
IWiaItem ***pIWiaItems)
|
|
{
|
|
DBG_FN(CWiaItem::DeviceDlg);
|
|
DBG_ERR(("CWiaItem::DeviceDlg, Bad Proxy"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetRootItem
|
|
*
|
|
* return interface to root item
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ppIWiaItem - return IWiaItem interface
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 10/20/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::GetRootItem(IWiaItem **ppIWiaItem)
|
|
{
|
|
DBG_FN(CWiaItem::GetRootItem);
|
|
HRESULT hr = S_OK;
|
|
LONG lDevErrVal;
|
|
|
|
//
|
|
// verify root is valid
|
|
//
|
|
|
|
if (m_pIWiaItemRoot != NULL) {
|
|
|
|
m_pIWiaItemRoot->AddRef();
|
|
*ppIWiaItem = m_pIWiaItemRoot;
|
|
|
|
} else {
|
|
DBG_ERR(("CWiaItem::GetRootItem: Bad Root item pointer"));
|
|
hr = E_FAIL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* FindItemByName
|
|
*
|
|
* Find an item based on its full name. Full name must be of the format.
|
|
*
|
|
* DeviceID\RootDir\[sub-dirs]\ItemName
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lFalgs
|
|
* bstrFullItemName
|
|
* ppIWiaItem
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 10/9/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::FindItemByName(
|
|
LONG lFlags,
|
|
BSTR bstrFullItemName,
|
|
IWiaItem **ppIWiaItem)
|
|
{
|
|
DBG_FN(CWiaItem::FindItemByName);
|
|
HRESULT hr;
|
|
|
|
if (bstrFullItemName == NULL) {
|
|
DBG_WRN(("CWiaItem::FindItemByName, bstrFullItemName parameter is NULL"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::FindItemByName, ValidateWiaDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
*ppIWiaItem = NULL;
|
|
|
|
//
|
|
// check for empty
|
|
//
|
|
|
|
if (wcscmp(bstrFullItemName, L"") == 0) {
|
|
DBG_ERR(("CWiaItem::FindItemByName, Full Item Name is NULL"));
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// try to find matching driver item from linear list
|
|
//
|
|
|
|
CWiaTree *pIChildItem;
|
|
|
|
//
|
|
// Make Sure the tree doesn't get deleted, then search the tree.
|
|
//
|
|
|
|
AddRef();
|
|
|
|
hr = m_pCWiaTree->FindItemByName(lFlags, bstrFullItemName, &pIChildItem);
|
|
|
|
//
|
|
// If the item was found, get the app item pointer and addref.
|
|
//
|
|
|
|
if (hr == S_OK) {
|
|
|
|
hr = pIChildItem->GetItemData((void**)ppIWiaItem);
|
|
|
|
if (hr == S_OK) {
|
|
(*ppIWiaItem)->AddRef();
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaItem::FindItemByName, bad item data"));
|
|
}
|
|
} else {
|
|
//DBG_WRN(("CWiaItem::FindItemByName, Item (%ws) not found in tree", bstrFullItemName));
|
|
}
|
|
|
|
Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* EnumDeviceCapabilities
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/15/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::EnumDeviceCapabilities(
|
|
LONG lFlags,
|
|
IEnumWIA_DEV_CAPS **ppIEnum)
|
|
{
|
|
DBG_FN(CWiaItem::EnumDeviceCapabilities);
|
|
|
|
//
|
|
// Corresponding driver item must be valid.
|
|
//
|
|
|
|
HRESULT hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumDeviceCapabilities, ValidateWiaDrvItemAccess failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumDeviceCapabilities, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add support for flags later.
|
|
//
|
|
|
|
CEnumDC *pEnum = new CEnumDC();;
|
|
|
|
if (!pEnum) {
|
|
DBG_ERR(("CWiaItem::EnumDeviceCapabilities, new CEnumDC failed"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pEnum->Initialize(lFlags, this);
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = pEnum->QueryInterface(IID_IEnumWIA_DEV_CAPS, (void **) ppIEnum);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumDeviceCapabilities, QI for IID_IEnumWIA_DEV_CAPS failed"));
|
|
delete pEnum;
|
|
}
|
|
} else {
|
|
DBG_ERR(("CWiaItem::EnumDeviceCapabilities, call to Initialize failed"));
|
|
delete pEnum;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* EnumRegisterEventInfo
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/15/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT _stdcall CWiaItem::EnumRegisterEventInfo(
|
|
LONG lFlags,
|
|
const GUID *pEventGUID,
|
|
IEnumWIA_DEV_CAPS **ppIEnumDevCap)
|
|
{
|
|
DBG_FN(CWiaItem::EnumRegisterEventInfo);
|
|
HRESULT hr;
|
|
LONG lItemType;
|
|
PROPSPEC propSpec[1];
|
|
PROPVARIANT propVar[1];
|
|
|
|
//
|
|
// Retrieve the item type and check whether it is the root item
|
|
//
|
|
|
|
hr = m_pWiaDrvItem->GetItemFlags(&lItemType);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumRegisterEventInfo() : Failed to get item type"));
|
|
return (hr);
|
|
}
|
|
|
|
if (! (lItemType & WiaItemTypeRoot)) {
|
|
DBG_ERR(("CWiaItem::EnumRegisterEventInfo() : Called on non-root item"));
|
|
return (E_INVALIDARG);
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumRegisterEventInfo, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve the Device ID from root item's property
|
|
//
|
|
|
|
propSpec->ulKind = PRSPEC_PROPID;
|
|
propSpec->propid = WIA_DIP_DEV_ID;
|
|
hr = ReadMultiple(1, propSpec, propVar);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::EnumRegisterEventInfo() : Failed to get device id"));
|
|
return (hr);
|
|
}
|
|
|
|
//
|
|
// Ask the Event Notifier to create the enumerator
|
|
//
|
|
|
|
hr = g_eventNotifier.CreateEnumEventInfo(
|
|
propVar->bstrVal,
|
|
pEventGUID,
|
|
ppIEnumDevCap);
|
|
|
|
//
|
|
// Garbage collection
|
|
//
|
|
|
|
PropVariantClear(propVar);
|
|
return (hr);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::Diagnostic
|
|
*
|
|
* Pass through to USD's diagnostic.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ulSize - the size of the buffer in bytes
|
|
* pBuffer - a pointer to the Diagnostic information buffer
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 12/14/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::Diagnostic(
|
|
ULONG ulSize,
|
|
BYTE *pBuffer)
|
|
{
|
|
DBG_FN(CWiaItem::Diagnostic);
|
|
IStiUSD *pIStiUSD;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = ValidateWiaDrvItemAccess(m_pWiaDrvItem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::Diagnostic() : Driver Item not valid!"));
|
|
return hr;
|
|
}
|
|
|
|
_try {
|
|
|
|
//
|
|
// Get IStiUsd
|
|
//
|
|
|
|
if (m_pActiveDevice) {
|
|
//
|
|
// Call diagnostic
|
|
//
|
|
|
|
{
|
|
LOCK_WIA_DEVICE _LWD(this, &hr);
|
|
|
|
if(SUCCEEDED(hr)) {
|
|
hr = m_pActiveDevice->m_DrvWrapper.STI_Diagnostic((STI_DIAG*)pBuffer);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
DBG_ERR(("CWiaItem::Diagnostic() : invalid MiniDriver interface"));
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBG_ERR(("CWiaItem::Diagnostic() : Exception in USD!"));
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::DumpItemData
|
|
*
|
|
* Allocate buffer and dump formated private CWiaItem data into it.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DumpItemData(BSTR *bstrItemData)
|
|
{
|
|
DBG_FN(CWiaItem::DumpItemData);
|
|
#ifdef ITEMDEBUG
|
|
|
|
#define BUF_SIZE 2048
|
|
#define LINE_SIZE 128
|
|
|
|
|
|
WCHAR szTemp[BUF_SIZE];
|
|
LPOLESTR psz = szTemp;
|
|
BSTR bstr;
|
|
|
|
psz+= wsprintfW(psz, L"App item, CWiaItem: %08X\r\n\r\n", this);
|
|
psz+= wsprintfW(psz, L"Address Member Value\r\n\r\n");
|
|
psz+= wsprintfW(psz, L"%08X m_ulSig: %08X\r\n", &m_ulSig, m_ulSig);
|
|
psz+= wsprintfW(psz, L"%08X m_cRef: %08X\r\n", &m_cRef, m_cRef);
|
|
psz+= wsprintfW(psz, L"%08X m_pWiaDrvItem: %08X\r\n", &m_pWiaDrvItem, m_pWiaDrvItem);
|
|
psz+= wsprintfW(psz, L"%08X m_pActiveDevice: %08X\r\n", &m_pActiveDevice, m_pActiveDevice);
|
|
psz+= wsprintfW(psz, L"%08X m_pIUnknownInner: %08X\r\n", &m_pIUnknownInner, m_pIUnknownInner);
|
|
psz+= wsprintfW(psz, L"%08X m_pCWiaTree: %08X\r\n", &m_pCWiaTree, m_pCWiaTree);
|
|
psz+= wsprintfW(psz, L"%08X m_pIWiaItemRoot: %08X\r\n", &m_pIWiaItemRoot, m_pIWiaItemRoot);
|
|
psz+= wsprintfW(psz, L"%08X m_pPropStg: %08X\r\n", &m_pPropStg, m_pPropStg);
|
|
psz+= wsprintfW(psz, L"%08X m_hBandSection: %08X\r\n", &m_hBandSection, m_hBandSection);
|
|
psz+= wsprintfW(psz, L"%08X m_pBandBuffer: %08X\r\n", &m_pBandBuffer, m_pBandBuffer);
|
|
psz+= wsprintfW(psz, L"%08X m_lBandBufferLength: %08X\r\n", &m_lBandBufferLength, m_lBandBufferLength);
|
|
psz+= wsprintfW(psz, L"%08X m_ClientBaseAddress: %08X\r\n", &m_ClientBaseAddress, m_ClientBaseAddress);
|
|
psz+= wsprintfW(psz, L"%08X m_bMapSection: %08X\r\n", &m_bMapSection, m_bMapSection);
|
|
psz+= wsprintfW(psz, L"%08X m_cfeBandedTran: %08X\r\n", &m_cwfiBandedTran, m_cwfiBandedTran);
|
|
psz+= wsprintfW(psz, L"%08X m_pfeBandedTran: %08X\r\n", &m_pwfiBandedTran, m_pwfiBandedTran);
|
|
|
|
if (psz > (szTemp + (BUF_SIZE - LINE_SIZE))) {
|
|
DBG_ERR(("CWiaItem::DumpItemData buffer too small"));
|
|
}
|
|
|
|
bstr = SysAllocString(szTemp);
|
|
if (bstr) {
|
|
*bstrItemData = bstr;
|
|
return S_OK;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
#else
|
|
return E_NOTIMPL;
|
|
#endif
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::DumpDrvItemData
|
|
*
|
|
* Allocate buffer and dump formated private CWiaDrvItem data into it.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DumpDrvItemData(BSTR *bstrDrvItemData)
|
|
{
|
|
DBG_FN(CWiaItem::DumpDrvItemData);
|
|
#ifdef DEBUG
|
|
if (m_pWiaDrvItem) {
|
|
return m_pWiaDrvItem->DumpItemData(bstrDrvItemData);
|
|
}
|
|
else {
|
|
*bstrDrvItemData = SysAllocString(L"No linkage to driver item");
|
|
if (*bstrDrvItemData) {
|
|
return S_OK;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
#else
|
|
return E_NOTIMPL;
|
|
#endif
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::DumpTreeItemData
|
|
*
|
|
* Allocate buffer and dump formated private CWiaTree data into it.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::DumpTreeItemData(BSTR *bstrTreeItemData)
|
|
{
|
|
DBG_FN(CWiaItem::DumpTreeItemData);
|
|
#ifdef DEBUG
|
|
if (m_pCWiaTree) {
|
|
return m_pCWiaTree->DumpTreeData(bstrTreeItemData);
|
|
}
|
|
else {
|
|
*bstrTreeItemData = SysAllocString(L"No linkage to tree item");
|
|
if (*bstrTreeItemData) {
|
|
return S_OK;
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
#else
|
|
return E_NOTIMPL;
|
|
#endif
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetTreePtr
|
|
*
|
|
* Returns a pointer to an items corresponding tree entry.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Pointer to a tree item on success, null if failure.
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaTree* _stdcall CWiaItem::GetTreePtr(void)
|
|
{
|
|
DBG_FN(CWiaItem::GetTreePtr);
|
|
if (m_pCWiaTree) {
|
|
return m_pCWiaTree;
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaItem::GetTreePtr NULL tree item pointer for item: %X", this));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetDrvItemPtr
|
|
*
|
|
* Returns a pointer to an items corresponding driver item.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Pointer to a driver item on success, null if failure.
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
CWiaDrvItem* _stdcall CWiaItem::GetDrvItemPtr(void)
|
|
{
|
|
DBG_FN(CWiaItem::GetDrvItemPtr);
|
|
if (m_pWiaDrvItem) {
|
|
return m_pWiaDrvItem;
|
|
}
|
|
else {
|
|
DBG_ERR(("CWiaItem::GetDrvItemPtr NULL driver item pointer for item: %X", this));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::WriteItemPropNames
|
|
*
|
|
* Write property names to all internal property storage.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::WriteItemPropNames(
|
|
LONG cItemProps,
|
|
PROPID *ppId,
|
|
LPOLESTR *ppszNames)
|
|
{
|
|
DBG_FN(CWiaItem::WriteItemPropNames);
|
|
if (IsBadReadPtr(ppId, sizeof(PROPID) * cItemProps) ||
|
|
IsBadReadPtr(ppszNames, sizeof(LPOLESTR) * cItemProps)) {
|
|
DBG_ERR(("CWiaItem::WriteItemPropNames, NULL input pointer"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
HRESULT hr = m_pPropStg->WriteItemPropNames(cItemProps,
|
|
ppId,
|
|
ppszNames);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::WriteItemPropNames, WritePropertyNames failed (0x%X)", hr));
|
|
return hr;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::GetItemPropStreams
|
|
*
|
|
* Get pointers to all internal property storage.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 1/19/1999 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HRESULT _stdcall CWiaItem::GetItemPropStreams(
|
|
IPropertyStorage **ppIPropStg,
|
|
IPropertyStorage **ppIPropAccessStg,
|
|
IPropertyStorage **ppIPropValidStg,
|
|
IPropertyStorage **ppIPropOldStg)
|
|
{
|
|
DBG_FN(CWiaItem::GetItemPropStreams);
|
|
HRESULT hr;
|
|
|
|
if (!m_pPropStg) {
|
|
DBG_ERR(("CWiaItem::GetItemPropStreams, NULL internal property storage pointer"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Check whether item properties have been initialized
|
|
//
|
|
|
|
if (!m_bInitialized) {
|
|
|
|
hr = InitLazyProps();
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::GetItemPropStreams, InitLazyProps failed"));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if (ppIPropStg) {
|
|
*ppIPropStg = m_pPropStg->CurStg();
|
|
}
|
|
|
|
if (ppIPropAccessStg) {
|
|
*ppIPropAccessStg = m_pPropStg->AccessStg();
|
|
}
|
|
|
|
if (ppIPropValidStg) {
|
|
*ppIPropValidStg = m_pPropStg->ValidStg();
|
|
}
|
|
|
|
if (ppIPropOldStg) {
|
|
*ppIPropOldStg = m_pPropStg->OldStg();
|
|
if (!(*ppIPropOldStg)) {
|
|
//
|
|
// Note that if the old property storage is NULL, we
|
|
// return the current value storage
|
|
//
|
|
*ppIPropOldStg = m_pPropStg->CurStg();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* CWiaItem::AddVolumePropertiesToRoot
|
|
*
|
|
* This helper method takes a Root WiaItem and adds any volume specific
|
|
* properties to it. Note that this should only be called on the Root
|
|
* item of Volume devices.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pActiveDevice - Pointer to Root's active device object
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
* History:
|
|
*
|
|
* 12/13/2000 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT CWiaItem::AddVolumePropertiesToRoot(
|
|
ACTIVE_DEVICE *pActiveDevice)
|
|
{
|
|
DBG_FN(AddVolumePropertiesToRoot);
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// To add new FIle SYstem properties:
|
|
// Simply add the appropriate entries to
|
|
// piFileSystem
|
|
// psFileSystem
|
|
// pwszFileSystem
|
|
// pwszFileSystem
|
|
// wpiFileSystem
|
|
// Then, don't forget to add the current value entries to
|
|
// pvFileSystem
|
|
// before doing a WriteMultiple. Notice that PropVariant arrays
|
|
// cannot be statically initialized (will give problems on 64bit)
|
|
//
|
|
PROPID piFileSystem[] = {WIA_DPF_MOUNT_POINT};
|
|
PROPSPEC psFileSystem[] = {
|
|
{PRSPEC_PROPID, WIA_DPF_MOUNT_POINT}
|
|
};
|
|
LPOLESTR pwszFileSystem[] = {WIA_DPF_MOUNT_POINT_STR};
|
|
|
|
WIA_PROPERTY_INFO wpiFileSystem[] = {
|
|
{WIA_PROP_RNC, VT_BSTR, 0, 0, 0, 0}, // WIA_DPF_MOUNT_POINT
|
|
};
|
|
|
|
PROPVARIANT pvFileSystem[sizeof(piFileSystem) / sizeof(piFileSystem[0])];
|
|
|
|
//
|
|
// Write the File System property names.
|
|
//
|
|
|
|
hr = WriteItemPropNames(sizeof(piFileSystem) / sizeof(piFileSystem[0]),
|
|
piFileSystem,
|
|
pwszFileSystem);
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CWiaItem::AddVolumePropertiesToRoot, WritePropNames failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Write the File System property values
|
|
//
|
|
|
|
ULONG ulIndex;
|
|
|
|
memset(pvFileSystem, 0, sizeof(pvFileSystem));
|
|
|
|
BSTR bstrMountPoint = NULL;
|
|
DEVICE_INFO *pDevInfo = pActiveDevice->m_DrvWrapper.getDevInfo();
|
|
|
|
if (pDevInfo) {
|
|
bstrMountPoint = SysAllocString(pDevInfo->wszAlternateID);
|
|
}
|
|
|
|
pvFileSystem[0].vt = VT_BSTR;
|
|
pvFileSystem[0].bstrVal = bstrMountPoint;
|
|
|
|
hr = (m_pPropStg->CurStg())->WriteMultiple(sizeof(piFileSystem) / sizeof(piFileSystem[0]),
|
|
psFileSystem,
|
|
pvFileSystem,
|
|
WIA_DPF_FIRST);
|
|
FreePropVariantArray(sizeof(piFileSystem) / sizeof(piFileSystem[0]),
|
|
pvFileSystem);
|
|
if (FAILED(hr)) {
|
|
ReportReadWriteMultipleError(hr, "CWiaItem::AddVolumePropertiesToRoot", NULL, FALSE, WIA_NUM_DIP, g_psDeviceInfo);
|
|
DBG_ERR(("CWiaItem::AddVolumePropertiesToRoot failed"));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Write out the File System property attributes
|
|
//
|
|
|
|
hr = wiasSetItemPropAttribs((BYTE*)this,
|
|
sizeof(piFileSystem) / sizeof(piFileSystem[0]),
|
|
psFileSystem,
|
|
wpiFileSystem);
|
|
|
|
return hr;
|
|
}
|
|
|