#ifndef __WIAITEM_H_INCLUDED #define __WIAITEM_H_INCLUDED #include #include #include #include #include #include "pshelper.h" #include "propstrm.h" #include "resource.h" #include "gphelper.h" #include "wiaffmt.h" class CWiaItem { public: // // Used to store the region for the scanner // struct CScanRegionSettings { SIZE sizeResolution; POINT ptOrigin; SIZE sizeExtent; }; private: CComPtr m_pWiaItem; DWORD m_dwGlobalInterfaceTableCookie; bool m_bSelectedForDownload; HBITMAP m_hBitmapImage; PBYTE m_pBitmapData; LONG m_nWidth; LONG m_nHeight; LONG m_nBitmapDataLength; CScanRegionSettings m_ScanRegionSettings; CPropertyStream m_SavedPropertyStream; CPropertyStream m_CustomPropertyStream; bool m_bDeleted; bool m_bAttemptedThumbnailDownload; mutable LONG m_nItemType; CWiaItem *m_pParent; CWiaItem *m_pChildren; CWiaItem *m_pNext; GUID m_guidDefaultFormat; LONG m_nAccessRights; LONG m_nImageWidth; LONG m_nImageHeight; int m_nRotationAngle; CSimpleStringWide m_strwFullItemName; CSimpleStringWide m_strwItemName; CAnnotationType m_AnnotationType; CSimpleString m_strDefExt; private: // No implementation CWiaItem(void); CWiaItem( const CWiaItem & ); CWiaItem &operator=( const CWiaItem & ); public: explicit CWiaItem( IWiaItem *pWiaItem ) : m_pWiaItem(pWiaItem), m_dwGlobalInterfaceTableCookie(0), m_bSelectedForDownload(false), m_hBitmapImage(NULL), m_pBitmapData(NULL), m_nWidth(0), m_nHeight(0), m_nBitmapDataLength(0), m_pParent(NULL), m_pChildren(NULL), m_pNext(NULL), m_guidDefaultFormat(IID_NULL), m_nRotationAngle(0), m_nAccessRights(0), m_nItemType(0), m_nImageWidth(0), m_nImageHeight(0), m_AnnotationType(AnnotationNone), m_bAttemptedThumbnailDownload(false) { WIA_PUSH_FUNCTION((TEXT("CWiaItem::CWiaItem"))); if (m_pWiaItem) { CComPtr pGlobalInterfaceTable; HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&pGlobalInterfaceTable ); if (SUCCEEDED(hr)) { hr = pGlobalInterfaceTable->RegisterInterfaceInGlobal( pWiaItem, IID_IWiaItem, &m_dwGlobalInterfaceTableCookie ); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("IGlobalInterfaceTable::RegisterInterfaceInGlobal gave us a cookie of %d"), m_dwGlobalInterfaceTableCookie )); } } // // NOTE: This is a here to get the item name so we can delete it later // in response to a delete event, because there is no other way to find an item // since ReadMultiple will fail after the item is deleted. This is the only item // property I read on the foreground thread during initialization, unfortunately. // but i need it immediately. One other awful alternative would be to just walk // the item tree and call ReadMultiple on each item and prune the ones that return // WIA_ERROR_ITEM_DELETED in response to delete item event. // PropStorageHelpers::GetProperty( m_pWiaItem, WIA_IPA_FULL_ITEM_NAME, m_strwFullItemName ); PropStorageHelpers::GetProperty( m_pWiaItem, WIA_IPA_ITEM_NAME, m_strwItemName ); } } ~CWiaItem(void) { WIA_PUSH_FUNCTION((TEXT("CWiaItem::~CWiaItem"))); // // Remove the item from the GIT // if (m_pWiaItem) { CComPtr pGlobalInterfaceTable; HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&pGlobalInterfaceTable ); if (SUCCEEDED(hr)) { hr = pGlobalInterfaceTable->RevokeInterfaceFromGlobal( m_dwGlobalInterfaceTableCookie ); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("IGlobalInterfaceTable::RevokeInterfaceFromGlobal succeeded on %d"), m_dwGlobalInterfaceTableCookie )); } } } // Delete the item's Thumbnail if (m_hBitmapImage) { DeleteObject(m_hBitmapImage); m_hBitmapImage = NULL; } // // Delete the thumbnail data // if (m_pBitmapData) { LocalFree(m_pBitmapData); m_pBitmapData = NULL; } // // NULL out all the other members // m_pWiaItem = NULL; m_dwGlobalInterfaceTableCookie = 0; m_nWidth = m_nHeight = m_nImageWidth = m_nImageHeight = m_nBitmapDataLength = 0; m_pParent = m_pChildren = m_pNext = NULL; } LONG ItemType(void) const { // // If we've already read the item type, don't read it again // if (!m_nItemType && m_pWiaItem) { (void)m_pWiaItem->GetItemType(&m_nItemType); } // // Return m_nItemType even if IWiaItem::GetItemType fails, because it will still be 0, which // also works as an error result // return m_nItemType; } bool Deleted(void) const { return m_bDeleted; } void MarkDeleted(void) { m_bDeleted = true; m_bSelectedForDownload = false; } bool RotationEnabled( bool bAllowUninitializedRotation=false ) const { WIA_PUSH_FUNCTION((TEXT("CWiaItem::RotationEnabled(%d)"),bAllowUninitializedRotation)); // // If this image doesn't have a thumbnail AND we tried to get the thumbnail, don't allow // rotation even if the caller says it is OK. This image doesn't have a thumbnail // because it didn't provide one, not because we don't have one yet // if (m_bAttemptedThumbnailDownload && !HasThumbnail()) { return false; } // // If this is an uninitialized image and we are told to allow uninitialized rotation, // we will allow rotation, which we will discard when the image is initialized. // if (bAllowUninitializedRotation && m_guidDefaultFormat==IID_NULL && m_nImageWidth==0 && m_nImageHeight==0) { WIA_TRACE((TEXT("Uninitialized image: returning true"))); return true; } return WiaUiUtil::CanWiaImageBeSafelyRotated( m_guidDefaultFormat, m_nImageWidth, m_nImageHeight ); } bool AttemptedThumbnailDownload( bool bAttemptedThumbnailDownload ) { return (m_bAttemptedThumbnailDownload = bAttemptedThumbnailDownload); } bool AttemptedThumbnailDownload() const { return m_bAttemptedThumbnailDownload; } void DiscardRotationIfNecessary(void) { WIA_PUSHFUNCTION(TEXT("CWiaItem::DiscardRotationIfNecessary")); // // After the image is initialized, we will discard the rotation angle if it turns out the // image cannot be rotated // if (!RotationEnabled()) { WIA_TRACE((TEXT("Discarding rotation"))); m_nRotationAngle = 0; } } bool IsValid(void) const { return(m_pWiaItem && m_dwGlobalInterfaceTableCookie); } CSimpleStringWide FullItemName(void) const { return m_strwFullItemName; } CSimpleStringWide ItemName(void) const { return m_strwItemName; } GUID DefaultFormat(void) { return m_guidDefaultFormat; } void DefaultFormat( const GUID &guidDefaultFormat ) { m_guidDefaultFormat = guidDefaultFormat; } LONG AccessRights(void) const { return m_nAccessRights; } void AccessRights( LONG nAccessRights ) { m_nAccessRights = nAccessRights; } void Rotate( bool bRight ) { switch (m_nRotationAngle) { case 0: m_nRotationAngle = bRight ? 90 : 270; break; case 90: m_nRotationAngle = bRight ? 180 : 0; break; case 180: m_nRotationAngle = bRight ? 270 : 90; break; case 270: m_nRotationAngle = bRight ? 0 : 180; break; } } int Rotation(void) const { return m_nRotationAngle; } CSimpleString DefExt() const { return m_strDefExt; } const CSimpleString &DefExt( const CSimpleString &strDefExt ) { return (m_strDefExt = strDefExt ); } CScanRegionSettings &ScanRegionSettings(void) { return m_ScanRegionSettings; } const CScanRegionSettings &ScanRegionSettings(void) const { return m_ScanRegionSettings; } CPropertyStream &SavedPropertyStream(void) { return m_SavedPropertyStream; } const CPropertyStream &SavedPropertyStream(void) const { return m_SavedPropertyStream; } CPropertyStream &CustomPropertyStream(void) { return m_CustomPropertyStream; } const CPropertyStream &CustomPropertyStream(void) const { return m_CustomPropertyStream; } bool SelectedForDownload(void) const { return m_bSelectedForDownload; } bool SelectedForDownload( bool bSelectedForDownload ) { return(m_bSelectedForDownload = bSelectedForDownload); } HBITMAP BitmapImage(void) const { return m_hBitmapImage; } HBITMAP BitmapImage( HBITMAP hBitmapImage ) { if (m_hBitmapImage) { DeleteObject(m_hBitmapImage); } return(m_hBitmapImage = hBitmapImage); } PBYTE BitmapData(void) const { return m_pBitmapData; } PBYTE BitmapData( PBYTE pBitmapData ) { if (m_pBitmapData) { LocalFree(m_pBitmapData); } return(m_pBitmapData = pBitmapData); } LONG Width(void) const { return m_nWidth; } LONG Width( LONG nWidth ) { return (m_nWidth = nWidth); } LONG Height(void) const { return m_nHeight; } LONG Height( LONG nHeight ) { return (m_nHeight = nHeight); } LONG BitmapDataLength(void) const { return m_nBitmapDataLength; } LONG BitmapDataLength( LONG nBitmapDataLength ) { return (m_nBitmapDataLength = nBitmapDataLength); } LONG ImageWidth(void) const { return m_nImageWidth; } LONG ImageWidth( LONG nImageWidth ) { return (m_nImageWidth = nImageWidth); } LONG ImageHeight(void) const { return m_nImageHeight; } LONG ImageHeight( LONG nImageHeight ) { return (m_nImageHeight = nImageHeight); } bool HasThumbnail() const { return (m_pBitmapData && m_nWidth && m_nHeight); } HBITMAP CreateThumbnailFromBitmapData( HDC hDC ) { // // Assume failure // HBITMAP hbmpResult = NULL; // // If we've already attempted to download this image // if (m_bAttemptedThumbnailDownload) { // // Make sure we have good data // if (m_pBitmapData && m_nWidth && m_nHeight) { // // Initialize the bitmap info // BITMAPINFO BitmapInfo = {0}; BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); BitmapInfo.bmiHeader.biWidth = m_nWidth; BitmapInfo.bmiHeader.biHeight = m_nHeight; BitmapInfo.bmiHeader.biPlanes = 1; BitmapInfo.bmiHeader.biBitCount = 24; BitmapInfo.bmiHeader.biCompression = BI_RGB; // // Create the bitmap // PBYTE pBits = NULL; hbmpResult = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 ); if (hbmpResult) { // // Calculate the size of the bitmap data // LONG nSizeOfBitmapData = WiaUiUtil::Align( m_nWidth * 3, sizeof(DWORD) ) * m_nHeight; // // Copy the bitmap data to the bitmap. Make sure we use the minimum of the calculated // and actual length // CopyMemory( pBits, m_pBitmapData, WiaUiUtil::Min(nSizeOfBitmapData,m_nBitmapDataLength) ); } else { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed!"))); } } } return hbmpResult; } HBITMAP CreateThumbnailBitmap( HWND hWnd, CGdiPlusHelper &GdiPlusHelper, int nSizeX, int nSizeY ) { // // Initialize the return value. Assume failure. // HBITMAP hThumbnail = NULL; // // Only return a bitmap if we've already attempted to download one // if (m_bAttemptedThumbnailDownload) { // // Make sure this is a real thumbnail. If not, we will create a fake one below. // if (HasThumbnail()) { // // Get the client DC // HDC hDC = GetDC( hWnd ); if (hDC) { // // Create the bitmap from the raw bitmap data // HBITMAP hRawBitmap = CreateThumbnailFromBitmapData( hDC ); if (hRawBitmap) { // // Rotate the thumbnail // HBITMAP hRotatedThumbnail = NULL; if (SUCCEEDED(GdiPlusHelper.Rotate( hRawBitmap, hRotatedThumbnail, Rotation()))) { // // Make sure we got a valid rotated thumbnail // if (hRotatedThumbnail) { // // Try to scale the image // SIZE sizeScaled = {nSizeX,nSizeY}; ScaleImage( hDC, hRotatedThumbnail, hThumbnail, sizeScaled ); // // Nuke the rotated bitmap // DeleteBitmap(hRotatedThumbnail); } } // // Nuke the raw bitmap // DeleteBitmap(hRawBitmap); } // // Release the client DC // ReleaseDC( hWnd, hDC ); } } else { WIA_PRINTGUID((m_guidDefaultFormat,TEXT("m_guidDefaultFormat"))); // // Create a file format object and load the type icon // CWiaFileFormat WiaFileFormat; WiaFileFormat.Format( m_guidDefaultFormat ); WiaFileFormat.Extension( m_strDefExt ); HICON hIcon = WiaFileFormat.AcquireIcon( NULL, false ); // // Make sure we have an icon // if (hIcon) { // // Create the icon thumbnail with the type icon and the name of the file // hThumbnail = WiaUiUtil::CreateIconThumbnail( hWnd, nSizeX, nSizeY, hIcon, CSimpleStringConvert::NaturalString(m_strwItemName) ); WIA_TRACE((TEXT("hThumbnail: %p"),hThumbnail)); // // Destroy the icon to prevent leaks // DestroyIcon(hIcon); } else { WIA_ERROR((TEXT("Unable to get the icon"))); } } } return hThumbnail; } HBITMAP CreateThumbnailBitmap( HDC hDC ) { // // Assume failure // HBITMAP hbmpResult = NULL; // // Make sure we have good data // WIA_TRACE((TEXT("m_pBitmapData: %08X, m_nWidth: %d, m_nWidth: %d"), m_pBitmapData, m_nWidth, m_nHeight )); if (m_pBitmapData && m_nWidth && m_nHeight) { // // Initialize the bitmap info // BITMAPINFO BitmapInfo = {0}; BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); BitmapInfo.bmiHeader.biWidth = m_nWidth; BitmapInfo.bmiHeader.biHeight = m_nHeight; BitmapInfo.bmiHeader.biPlanes = 1; BitmapInfo.bmiHeader.biBitCount = 24; BitmapInfo.bmiHeader.biCompression = BI_RGB; // // Create the bitmap // PBYTE pBits = NULL; hbmpResult = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 ); if (hbmpResult) { LONG nSizeOfBitmapData = WiaUiUtil::Align( m_nWidth * 3, sizeof(DWORD) ) * m_nHeight; CopyMemory( pBits, m_pBitmapData, WiaUiUtil::Min(nSizeOfBitmapData,m_nBitmapDataLength) ); } else { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed!"))); } } return hbmpResult; } IWiaItem *WiaItem(void) const { return m_pWiaItem.p; } IWiaItem *WiaItem(void) { return m_pWiaItem.p; } const CWiaItem *Next(void) const { return(m_pNext); } CWiaItem *Next(void) { return(m_pNext); } CWiaItem *Next( CWiaItem *pNext ) { return(m_pNext = pNext); } const CWiaItem *Children(void) const { return(m_pChildren); } CWiaItem *Children(void) { return(m_pChildren); } CWiaItem *Children( CWiaItem *pChildren ) { return(m_pChildren = pChildren); } const CWiaItem *Parent(void) const { return(m_pParent); } CWiaItem *Parent(void) { return(m_pParent); } CWiaItem *Parent( CWiaItem *pParent ) { return(m_pParent = pParent); } DWORD GlobalInterfaceTableCookie(void) const { return m_dwGlobalInterfaceTableCookie; } bool operator==( const CWiaItem &WiaItem ) { return(WiaItem.WiaItem() == m_pWiaItem.p); } bool operator==( DWORD dwGlobalInterfaceTableCookie ) { return(dwGlobalInterfaceTableCookie == GlobalInterfaceTableCookie()); } bool IsDownloadableItemType(void) const { LONG nItemType = ItemType(); return ((nItemType & WiaItemTypeImage) || (nItemType & WiaItemTypeVideo)); } CAnnotationType AnnotationType(void) const { return m_AnnotationType; } void AnnotationType( CAnnotationType AnnotationType ) { m_AnnotationType = AnnotationType; } }; class CWiaItemList { public: enum CEnumEvent { CountingItems, // Recursing tree, counting items. nData == current count ReadingItemInfo // Recursing tree, reading info. nData == current item }; typedef bool (*WiaItemEnumerationCallbackFunction)( CEnumEvent EnumEvent, UINT nData, LPARAM lParam, bool bForceUpdate ); private: CWiaItem *m_pRoot; private: // No implementation CWiaItemList( const CWiaItemList & ); CWiaItemList &operator=( const CWiaItemList & ); public: CWiaItemList(void) : m_pRoot(NULL) { } ~CWiaItemList(void) { Destroy(); } void Destroy( CWiaItem *pRoot ) { while (pRoot) { Destroy(pRoot->Children()); CWiaItem *pCurr = pRoot; pRoot = pRoot->Next(); delete pCurr; } } void Destroy(void) { Destroy(m_pRoot); m_pRoot = NULL; } const CWiaItem *Root(void) const { return(m_pRoot); } CWiaItem *Root(void) { return(m_pRoot); } CWiaItem *Root( CWiaItem *pRoot ) { return(m_pRoot = pRoot); } int Count( CWiaItem *pFirst ) { int nCount = 0; for (CWiaItem *pCurr = pFirst;pCurr;pCurr = pCurr->Next()) { if (pCurr->IsDownloadableItemType() && !pCurr->Deleted()) nCount++; nCount += Count(pCurr->Children()); } return nCount; } int Count(void) { return Count(m_pRoot); } int SelectedForDownloadCount( CWiaItem *pFirst ) { int nCount = 0; for (CWiaItem *pCurr = pFirst;pCurr;pCurr = pCurr->Next()) { if (pCurr->IsDownloadableItemType() && pCurr->SelectedForDownload()) nCount++; nCount += SelectedForDownloadCount(pCurr->Children()); } return nCount; } int SelectedForDownloadCount(void) { return SelectedForDownloadCount(Root()); } static CWiaItem *Find( CWiaItem *pRoot, const CWiaItem *pNode ) { for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next()) { if (*pCurr == *pNode) { if (!pCurr->Deleted()) { return pCurr; } } if (pCurr->Children()) { CWiaItem *pFind = Find( pCurr->Children(), pNode ); if (pFind) { return pFind; } } } return(NULL); } CWiaItem *Find( CWiaItem *pNode ) { return(Find( m_pRoot, pNode )); } static CWiaItem *Find( CWiaItem *pRoot, IWiaItem *pItem ) { for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next()) { if (pCurr->WiaItem() == pItem) { if (!pCurr->Deleted()) { return pCurr; } } if (pCurr->Children()) { CWiaItem *pFind = Find( pCurr->Children(), pItem ); if (pFind) { return pFind; } } } return(NULL); } CWiaItem *Find( IWiaItem *pItem ) { return(Find( m_pRoot, pItem )); } static CWiaItem *Find( CWiaItem *pRoot, LPCWSTR pwszFindName ) { for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next()) { if (CSimpleStringConvert::NaturalString(CSimpleStringWide(pwszFindName)) == CSimpleStringConvert::NaturalString(pCurr->FullItemName())) { if (!pCurr->Deleted()) { return pCurr; } } if (pCurr->Children()) { CWiaItem *pFind = Find( pCurr->Children(), pwszFindName ); if (pFind) { return pFind; } } } return(NULL); } CWiaItem *Find( LPCWSTR pwszFindName ) { return(Find( m_pRoot, pwszFindName )); } static CWiaItem *Find( CWiaItem *pRoot, DWORD dwGlobalInterfaceTableCookie ) { for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next()) { if (pCurr->GlobalInterfaceTableCookie() == dwGlobalInterfaceTableCookie) { if (!pCurr->Deleted()) { return pCurr; } } if (pCurr->Children()) { CWiaItem *pFind = Find( pCurr->Children(), dwGlobalInterfaceTableCookie ); if (pFind) { return pFind; } } } return(NULL); } CWiaItem *Find( DWORD dwGlobalInterfaceTableCookie ) { return(Find( m_pRoot, dwGlobalInterfaceTableCookie )); } HRESULT Add( CWiaItem *pParent, CWiaItem *pNewWiaItemNode ) { WIA_PUSHFUNCTION(TEXT("CWiaItemList::Add")); WIA_TRACE((TEXT("Root(): 0x%08X"), Root())); if (pNewWiaItemNode) { if (!Root()) { Root(pNewWiaItemNode); pNewWiaItemNode->Parent(NULL); pNewWiaItemNode->Children(NULL); pNewWiaItemNode->Next(NULL); } else { if (!pParent) { CWiaItem *pCurr=Root(); while (pCurr && pCurr->Next()) { pCurr=pCurr->Next(); } pCurr->Next(pNewWiaItemNode); pNewWiaItemNode->Next(NULL); pNewWiaItemNode->Children(NULL); pNewWiaItemNode->Parent(NULL); } else if (!pParent->Children()) { pParent->Children(pNewWiaItemNode); pNewWiaItemNode->Next(NULL); pNewWiaItemNode->Children(NULL); pNewWiaItemNode->Parent(pParent); } else { CWiaItem *pCurr=pParent->Children(); while (pCurr && pCurr->Next()) { pCurr=pCurr->Next(); } pCurr->Next(pNewWiaItemNode); pNewWiaItemNode->Next(NULL); pNewWiaItemNode->Children(NULL); pNewWiaItemNode->Parent(pParent); } } } return S_OK; } HRESULT EnumerateItems( CWiaItem *pCurrentParent, IEnumWiaItem *pEnumWiaItem, int &nCurrentItem, WiaItemEnumerationCallbackFunction pfnWiaItemEnumerationCallback = NULL, LPARAM lParam = 0 ) { WIA_PUSHFUNCTION(TEXT("CWiaItemList::EnumerateItems")); // // Assume failure // HRESULT hr = E_FAIL; // // Make sure we have a valid enumerator // if (pEnumWiaItem != NULL) { // // Start at the beginning // hr = pEnumWiaItem->Reset(); while (hr == S_OK) { // // Get the next item // CComPtr pWiaItem; hr = pEnumWiaItem->Next(1, &pWiaItem, NULL); if (S_OK == hr) { if (pfnWiaItemEnumerationCallback) { bool bContinue = pfnWiaItemEnumerationCallback( ReadingItemInfo, nCurrentItem, lParam, false ); if (!bContinue) { hr = S_FALSE; break; } } // // Create a CWiaItem wrapper // CWiaItem *pNewWiaItem = new CWiaItem( pWiaItem ); if (pNewWiaItem && pNewWiaItem->WiaItem()) { // // Get the item type // LONG nItemType = pNewWiaItem->ItemType(); if (nItemType) { // // Add it to the list // Add( pCurrentParent, pNewWiaItem ); // // If it is an image, mark it as downloadeable // if (pNewWiaItem->IsDownloadableItemType()) { pNewWiaItem->SelectedForDownload(true); nCurrentItem++; WIA_TRACE((TEXT("Found an image"))); } // // If it is not an image, mark it as downloadeable // else { pNewWiaItem->SelectedForDownload(false); WIA_TRACE((TEXT("Found something that is NOT an image"))); } // // If it is a folder, enumerate its child items and recurse // if (nItemType & WiaItemTypeFolder) { CComPtr pIEnumChildItem; if (S_OK == pWiaItem->EnumChildItems(&pIEnumChildItem)) { EnumerateItems( pNewWiaItem, pIEnumChildItem, nCurrentItem, pfnWiaItemEnumerationCallback, lParam ); } } } } } // // Since we are using S_FALSE for cancel, we need to break out of this loop and set hr to S_OK // else if (S_FALSE == hr) { hr = S_OK; break; } } } // // Call the callback function one more time, and force the update // if (pfnWiaItemEnumerationCallback) { bool bContinue = pfnWiaItemEnumerationCallback( ReadingItemInfo, nCurrentItem, lParam, true ); if (!bContinue) { hr = S_FALSE; } } return hr; } HRESULT EnumerateAllWiaItems( IWiaItem *pWiaRootItem, WiaItemEnumerationCallbackFunction pfnWiaItemEnumerationCallback = NULL, LPARAM lParam = 0 ) { // // Make sure we have a valid root item // if (!pWiaRootItem) { return E_INVALIDARG; } // // Enumerate the child items // CComPtr pEnumItem; HRESULT hr = pWiaRootItem->EnumChildItems(&pEnumItem); if (hr == S_OK) { int nItemCount = 0; // // Entry point to the recursive enumeration routine // hr = EnumerateItems( NULL, pEnumItem, nItemCount, pfnWiaItemEnumerationCallback, lParam ); } return hr; } }; #endif // __WIAITEM_H_INCLUDED