1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/uno/Any.hxx>
21 #include <com/sun/star/uno/Reference.hxx>
22 #include <com/sun/star/util/XCloseable.hpp>
23 #include <com/sun/star/util/XCloseBroadcaster.hpp>
24 #include <com/sun/star/util/XCloseListener.hpp>
25 #include <com/sun/star/frame/XFrame.hpp>
26 #include <com/sun/star/frame/Desktop.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <cppuhelper/implbase1.hxx>
29 #include <comphelper/processfactory.hxx>
34 #include <tools/stream.hxx>
35 #include <tools/helpers.hxx>
36 #include <osl/mutex.hxx>
37 #include <osl/module.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <vcl/sysdata.hxx>
41 #include "scanner.hxx"
44 #pragma warning (push,1)
45 #pragma warning (disable:4668)
47 #include "twain/twain.h"
52 using namespace ::com::sun::star
;
54 #define TWAIN_EVENT_NONE 0x00000000UL
55 #define TWAIN_EVENT_QUIT 0x00000001UL
56 #define TWAIN_EVENT_SCANNING 0x00000002UL
57 #define TWAIN_EVENT_XFER 0x00000004UL
60 #define PTWAINMSG MSG*
61 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
62 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
65 #define TWAIN_LIBNAME "TWAIN_32.DLL"
66 #define TWAIN_FUNCNAME "DSM_Entry"
72 TWAIN_STATE_SCANNING
= 1,
74 TWAIN_STATE_CANCELED
= 3
77 class ImpTwain
: public ::cppu::WeakImplHelper1
< util::XCloseListener
>
79 friend LRESULT CALLBACK
TwainMsgProc( int nCode
, WPARAM wParam
, LPARAM lParam
);
81 uno::Reference
< uno::XInterface
> mxSelfRef
;
82 uno::Reference
< scanner::XScannerManager
> mxMgr
;
83 ScannerManager
& mrMgr
;
84 TW_IDENTITY aAppIdent
;
85 TW_IDENTITY aSrcIdent
;
92 bool mbCloseFrameOnExit
;
94 bool ImplHandleMsg( void* pMsg
);
96 void ImplOpenSourceManager();
97 void ImplOpenSource();
98 bool ImplEnableSource();
100 void ImplFallback( ULONG_PTR nEvent
);
101 void ImplSendCloseEvent();
102 void ImplDeregisterCloseListener();
103 void ImplRegisterCloseListener();
104 uno::Reference
< frame::XFrame
> ImplGetActiveFrame();
105 uno::Reference
< util::XCloseBroadcaster
> ImplGetActiveFrameCloseBroadcaster();
107 DECL_LINK( ImplFallbackHdl
, void* );
108 DECL_LINK( ImplDestroyHdl
, void* );
110 // from util::XCloseListener
111 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
);
112 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
114 // from lang::XEventListener
115 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
119 ImpTwain( ScannerManager
& rMgr
, const Link
<>& rNotifyLink
);
128 static ImpTwain
* pImpTwainInstance
= NULL
;
130 LRESULT CALLBACK
TwainWndProc( HWND hWnd
,UINT nMsg
, WPARAM nPar1
, LPARAM nPar2
)
132 return DefWindowProc( hWnd
, nMsg
, nPar1
, nPar2
);
135 LRESULT CALLBACK
TwainMsgProc( int nCode
, WPARAM wParam
, LPARAM lParam
)
137 MSG
* pMsg
= (MSG
*) lParam
;
139 if( ( nCode
< 0 ) || ( pImpTwainInstance
->hTwainWnd
!= pMsg
->hwnd
) || !pImpTwainInstance
->ImplHandleMsg( (void*) lParam
) )
141 return CallNextHookEx( pImpTwainInstance
->hTwainHook
, nCode
, wParam
, lParam
);
145 pMsg
->message
= WM_USER
;
152 // #107835# hold reference to ScannerManager, to prevent premature death
153 ImpTwain::ImpTwain( ScannerManager
& rMgr
, const Link
<>& rNotifyLink
) :
154 mxMgr( uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( &rMgr
), uno::UNO_QUERY
) ),
156 aNotifyLink( rNotifyLink
),
162 mbCloseFrameOnExit( false )
164 // setup TWAIN window
165 pImpTwainInstance
= this;
168 aAppIdent
.Version
.MajorNum
= 1;
169 aAppIdent
.Version
.MinorNum
= 0;
170 aAppIdent
.Version
.Language
= TWLG_USA
;
171 aAppIdent
.Version
.Country
= TWCY_USA
;
172 aAppIdent
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
173 aAppIdent
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
174 aAppIdent
.SupportedGroups
= DG_IMAGE
| DG_CONTROL
;
175 strncpy( aAppIdent
.Version
.Info
, "8.0", 32 );
176 aAppIdent
.Version
.Info
[32] = aAppIdent
.Version
.Info
[33] = 0;
177 strncpy( aAppIdent
.Manufacturer
, "Sun Microsystems", 32 );
178 aAppIdent
.Manufacturer
[32] = aAppIdent
.Manufacturer
[33] = 0;
179 strncpy( aAppIdent
.ProductFamily
,"Office", 32 );
180 aAppIdent
.ProductFamily
[32] = aAppIdent
.ProductFamily
[33] = 0;
181 strncpy( aAppIdent
.ProductName
, "Office", 32 );
182 aAppIdent
.ProductName
[32] = aAppIdent
.ProductName
[33] = 0;
184 WNDCLASS aWc
= { 0, &TwainWndProc
, 0, sizeof( WNDCLASS
), GetModuleHandle( NULL
), NULL
, NULL
, NULL
, NULL
, "TwainClass" };
185 RegisterClass( &aWc
);
187 hTwainWnd
= CreateWindowEx( WS_EX_TOPMOST
, aWc
.lpszClassName
, "TWAIN", 0, 0, 0, 0, 0, HWND_DESKTOP
, NULL
, aWc
.hInstance
, 0 );
188 hTwainHook
= SetWindowsHookEx( WH_GETMESSAGE
, &TwainMsgProc
, NULL
, GetCurrentThreadId() );
190 // block destruction until ImplDestroyHdl is called
191 mxSelfRef
= static_cast< ::cppu::OWeakObject
* >( this );
194 ImpTwain::~ImpTwain()
196 // are we responsible for application shutdown?
197 if( mbCloseFrameOnExit
)
198 ImplSendCloseEvent();
201 void ImpTwain::Destroy()
203 ImplFallback( TWAIN_EVENT_NONE
);
204 Application::PostUserEvent( LINK( this, ImpTwain
, ImplDestroyHdl
), NULL
);
207 bool ImpTwain::SelectSource()
209 TW_UINT16 nRet
= TWRC_FAILURE
;
211 ImplOpenSourceManager();
217 aIdent
.Id
= 0, aIdent
.ProductName
[ 0 ] = '\0';
218 aNotifyLink
.Call( (void*) TWAIN_EVENT_SCANNING
);
219 nRet
= PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &aIdent
);
222 ImplFallback( TWAIN_EVENT_QUIT
);
224 return( TWRC_SUCCESS
== nRet
);
227 bool ImpTwain::InitXfer()
231 ImplOpenSourceManager();
238 bRet
= ImplEnableSource();
242 ImplFallback( TWAIN_EVENT_QUIT
);
247 void ImpTwain::ImplOpenSourceManager()
251 pMod
= new ::osl::Module( OUString() );
253 if( pMod
->load( OUString( TWAIN_LIBNAME
) ) )
257 pDSM
= (DSMENTRYPROC
) pMod
->getSymbol(OUString(TWAIN_FUNCNAME
));
259 ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, &hTwainWnd
) == TWRC_SUCCESS
) )
272 void ImpTwain::ImplOpenSource()
276 if( ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &aSrcIdent
) == TWRC_SUCCESS
) &&
277 ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &aSrcIdent
) == TWRC_SUCCESS
) )
279 TW_CAPABILITY aCap
= { CAP_XFERCOUNT
, TWON_ONEVALUE
, GlobalAlloc( GHND
, sizeof( TW_ONEVALUE
) ) };
280 TW_ONEVALUE
* pVal
= (TW_ONEVALUE
*) GlobalLock( aCap
.hContainer
);
282 pVal
->ItemType
= TWTY_INT16
, pVal
->Item
= 1;
283 GlobalUnlock( aCap
.hContainer
);
284 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &aCap
);
285 GlobalFree( aCap
.hContainer
);
291 bool ImpTwain::ImplEnableSource()
297 TW_USERINTERFACE aUI
= { true, true, hTwainWnd
};
299 aNotifyLink
.Call( (void*) TWAIN_EVENT_SCANNING
);
302 // register as vetoable close listener, to prevent application to die under us
303 ImplRegisterCloseListener();
305 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_USERINTERFACE
, MSG_ENABLEDS
, &aUI
) == TWRC_SUCCESS
)
313 // deregister as vetoable close listener, dialog failed
314 ImplDeregisterCloseListener();
321 bool ImpTwain::ImplHandleMsg( void* pMsg
)
324 PTWAINMSG pMess
= (PTWAINMSG
) pMsg
;
325 TW_EVENT aEvt
= { pMess
, MSG_NULL
};
327 nRet
= PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_EVENT
, MSG_PROCESSEVENT
, &aEvt
);
329 if( aEvt
.TWMessage
!= MSG_NULL
)
331 switch( aEvt
.TWMessage
)
335 ULONG_PTR nEvent
= TWAIN_EVENT_QUIT
;
342 if( mrMgr
.GetData() )
343 nEvent
= TWAIN_EVENT_XFER
;
346 ImplFallback( nEvent
);
351 ImplFallback( TWAIN_EVENT_QUIT
);
359 nRet
= TWRC_NOTDSEVENT
;
361 return( TWRC_DSEVENT
== nRet
);
364 void ImpTwain::ImplXfer()
370 long nWidth
, nHeight
, nXRes
, nYRes
;
372 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_IMAGE
, DAT_IMAGEINFO
, MSG_GET
, &aInfo
) == TWRC_SUCCESS
)
374 nWidth
= aInfo
.ImageWidth
;
375 nHeight
= aInfo
.ImageLength
;
376 nXRes
= FIXTOLONG( aInfo
.XResolution
);
377 nYRes
= FIXTOLONG( aInfo
.YResolution
);
380 nWidth
= nHeight
= nXRes
= nYRes
= -1L;
382 switch( PFUNC( &aAppIdent
, &aSrcIdent
, DG_IMAGE
, DAT_IMAGENATIVEXFER
, MSG_GET
, &hDIB
) )
388 case( TWRC_XFERDONE
):
392 if( ( nXRes
!= -1 ) && ( nYRes
!= - 1 ) && ( nWidth
!= - 1 ) && ( nHeight
!= - 1 ) )
394 // set resolution of bitmap
395 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( (HGLOBAL
) (sal_IntPtr
) hDIB
);
396 static const double fFactor
= 100.0 / 2.54;
398 pBIH
->biXPelsPerMeter
= FRound( fFactor
* nXRes
);
399 pBIH
->biYPelsPerMeter
= FRound( fFactor
* nYRes
);
401 GlobalUnlock( (HGLOBAL
) (sal_IntPtr
) hDIB
);
404 mrMgr
.SetData( (void*) (sal_IntPtr
) hDIB
);
407 GlobalFree( (HGLOBAL
) (sal_IntPtr
) hDIB
);
419 void ImpTwain::ImplFallback( ULONG_PTR nEvent
)
421 Application::PostUserEvent( LINK( this, ImpTwain
, ImplFallbackHdl
), (void*) nEvent
);
424 IMPL_LINK( ImpTwain
, ImplFallbackHdl
, void*, pData
)
426 const sal_uIntPtr nEvent
= (sal_uIntPtr
) pData
;
427 bool bFallback
= true;
434 TW_PENDINGXFERS aXfers
;
436 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_PENDINGXFERS
, MSG_ENDXFER
, &aXfers
) == TWRC_SUCCESS
)
438 if( aXfers
.Count
!= 0 )
439 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_PENDINGXFERS
, MSG_RESET
, &aXfers
);
448 TW_USERINTERFACE aUI
= { true, true, hTwainWnd
};
450 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_USERINTERFACE
, MSG_DISABLEDS
, &aUI
);
453 // deregister as vetoable close listener
454 ImplDeregisterCloseListener();
460 PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &aSrcIdent
);
467 PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, &hTwainWnd
);
482 if( nEvent
!= TWAIN_EVENT_NONE
)
483 aNotifyLink
.Call( (void*) nEvent
);
491 ImplFallback( nEvent
);
496 IMPL_LINK_NOARG( ImpTwain
, ImplDestroyHdl
)
499 DestroyWindow( hTwainWnd
);
502 UnhookWindowsHookEx( hTwainHook
);
504 // permit destruction of ourselves (normally, refcount
505 // should drop to zero exactly here)
507 pImpTwainInstance
= NULL
;
512 uno::Reference
< frame::XFrame
> ImpTwain::ImplGetActiveFrame()
516 // query desktop instance
517 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( ::comphelper::getProcessComponentContext() );
519 uno::Reference
< frame::XFrame
> xActiveFrame
= xDesktop
->getActiveFrame();
521 if( xActiveFrame
.is() )
526 catch( const uno::Exception
& )
530 OSL_FAIL("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
531 return uno::Reference
< frame::XFrame
>();
534 uno::Reference
< util::XCloseBroadcaster
> ImpTwain::ImplGetActiveFrameCloseBroadcaster()
538 return uno::Reference
< util::XCloseBroadcaster
>( ImplGetActiveFrame(), uno::UNO_QUERY
);
540 catch( const uno::Exception
& )
544 OSL_FAIL("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
545 return uno::Reference
< util::XCloseBroadcaster
>();
548 void ImpTwain::ImplRegisterCloseListener()
552 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( ImplGetActiveFrameCloseBroadcaster() );
554 if( xCloseBroadcaster
.is() )
556 xCloseBroadcaster
->addCloseListener(this);
557 return; // successfully registered as a close listener
561 // interface unknown. don't register, then
562 OSL_FAIL("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
566 catch( const uno::Exception
& )
570 OSL_FAIL("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
573 void ImpTwain::ImplDeregisterCloseListener()
577 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster(
578 ImplGetActiveFrameCloseBroadcaster() );
580 if( xCloseBroadcaster
.is() )
582 xCloseBroadcaster
->removeCloseListener(this);
583 return; // successfully deregistered as a close listener
587 // interface unknown. don't deregister, then
588 OSL_FAIL("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
592 catch( const uno::Exception
& )
596 OSL_FAIL("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
599 void SAL_CALL
ImpTwain::queryClosing( const lang::EventObject
& /*Source*/, sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
)
601 // shall we re-send the close query later on?
602 mbCloseFrameOnExit
= GetsOwnership
;
604 // the sole purpose of this listener is to forbid closing of the listened-at frame
605 throw util::CloseVetoException();
608 void SAL_CALL
ImpTwain::notifyClosing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
611 OSL_FAIL("ImpTwain::notifyClosing called, but we vetoed the closing before!");
614 void SAL_CALL
ImpTwain::disposing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
616 // we're not holding any references to the frame, thus noop
619 void ImpTwain::ImplSendCloseEvent()
623 uno::Reference
< util::XCloseable
> xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY
);
625 if( xCloseable
.is() )
626 xCloseable
->close( true );
628 catch( const uno::Exception
& )
632 OSL_FAIL("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
638 uno::Reference
< lang::XEventListener
> mxListener
;
639 uno::Reference
< scanner::XScannerManager
> mxMgr
;
640 const ScannerManager
* mpCurMgr
;
641 ImpTwain
* mpImpTwain
;
644 DECL_LINK( ImpNotifyHdl
, ImpTwain
* );
651 bool SelectSource( ScannerManager
& rMgr
);
652 bool PerformTransfer( ScannerManager
& rMgr
, const uno::Reference
< lang::XEventListener
>& rxListener
);
654 TwainState
GetState() const { return meState
; }
660 meState( TWAIN_STATE_NONE
)
667 mpImpTwain
->Destroy();
670 bool Twain::SelectSource( ScannerManager
& rMgr
)
676 // hold reference to ScannerManager, to prevent premature death
677 mxMgr
= uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( const_cast< ScannerManager
* >( mpCurMgr
= &rMgr
) ),
680 meState
= TWAIN_STATE_NONE
;
681 mpImpTwain
= new ImpTwain( rMgr
, LINK( this, Twain
, ImpNotifyHdl
) );
682 bRet
= mpImpTwain
->SelectSource();
690 bool Twain::PerformTransfer( ScannerManager
& rMgr
, const uno::Reference
< lang::XEventListener
>& rxListener
)
696 // hold reference to ScannerManager, to prevent premature death
697 mxMgr
= uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( const_cast< ScannerManager
* >( mpCurMgr
= &rMgr
) ),
700 mxListener
= rxListener
;
701 meState
= TWAIN_STATE_NONE
;
702 mpImpTwain
= new ImpTwain( rMgr
, LINK( this, Twain
, ImpNotifyHdl
) );
703 bRet
= mpImpTwain
->InitXfer();
711 IMPL_LINK( Twain
, ImpNotifyHdl
, ImpTwain
*, nEvent
)
713 switch( (sal_uIntPtr
)(void*) nEvent
)
715 case( TWAIN_EVENT_SCANNING
):
716 meState
= TWAIN_STATE_SCANNING
;
719 case( TWAIN_EVENT_QUIT
):
721 if( meState
!= TWAIN_STATE_DONE
)
722 meState
= TWAIN_STATE_CANCELED
;
726 mpImpTwain
->Destroy();
731 if( mxListener
.is() )
732 mxListener
->disposing( lang::EventObject( mxMgr
) );
738 case( TWAIN_EVENT_XFER
):
742 meState
= ( mpCurMgr
->GetData() ? TWAIN_STATE_DONE
: TWAIN_STATE_CANCELED
);
744 mpImpTwain
->Destroy();
748 if( mxListener
.is() )
749 mxListener
->disposing( lang::EventObject( mxMgr
) );
765 void ScannerManager::AcquireData()
769 void ScannerManager::ReleaseData()
773 GlobalFree( (HGLOBAL
)(sal_IntPtr
) mpData
);
778 awt::Size
ScannerManager::getSize() throw()
781 HGLOBAL hDIB
= (HGLOBAL
)(sal_IntPtr
) mpData
;
785 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( hDIB
);
789 aRet
.Width
= pBIH
->biWidth
;
790 aRet
.Height
= pBIH
->biHeight
;
793 aRet
.Width
= aRet
.Height
= 0;
795 GlobalUnlock( hDIB
);
798 aRet
.Width
= aRet
.Height
= 0;
803 uno::Sequence
< sal_Int8
> ScannerManager::getDIB() throw()
805 uno::Sequence
< sal_Int8
> aRet
;
809 HGLOBAL hDIB
= (HGLOBAL
)(sal_IntPtr
) mpData
;
810 const sal_uInt32 nDIBSize
= GlobalSize( hDIB
);
811 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( hDIB
);
815 sal_uInt32 nColEntries
;
817 switch( pBIH
->biBitCount
)
822 nColEntries
= pBIH
->biClrUsed
? pBIH
->biClrUsed
: ( 1 << pBIH
->biBitCount
);
826 nColEntries
= pBIH
->biClrUsed
? pBIH
->biClrUsed
: 0;
832 nColEntries
= pBIH
->biClrUsed
;
834 if( pBIH
->biCompression
== BI_BITFIELDS
)
844 aRet
= uno::Sequence
< sal_Int8
>( sizeof( BITMAPFILEHEADER
) + nDIBSize
);
846 sal_Int8
* pBuf
= aRet
.getArray();
847 SvMemoryStream
* pMemStm
= new SvMemoryStream( (char*) pBuf
, sizeof( BITMAPFILEHEADER
), StreamMode::WRITE
);
849 pMemStm
->WriteChar( 'B' ).WriteChar( 'M' ).WriteUInt32( 0 ).WriteUInt32( 0 );
850 pMemStm
->WriteUInt32( sizeof( BITMAPFILEHEADER
) + pBIH
->biSize
+ ( nColEntries
* sizeof( RGBQUAD
) ) );
853 memcpy( pBuf
+ sizeof( BITMAPFILEHEADER
), pBIH
, nDIBSize
);
856 GlobalUnlock( hDIB
);
863 uno::Sequence
< ScannerContext
> SAL_CALL
ScannerManager::getAvailableScanners() throw()
865 osl::MutexGuard
aGuard( maProtector
);
866 uno::Sequence
< ScannerContext
> aRet( 1 );
868 aRet
.getArray()[0].ScannerName
= "TWAIN" ;
869 aRet
.getArray()[0].InternalData
= 0;
874 sal_Bool SAL_CALL
ScannerManager::configureScannerAndScan( ScannerContext
& rContext
, const uno::Reference
< lang::XEventListener
>& )
875 throw (ScannerException
, RuntimeException
, std::exception
)
877 osl::MutexGuard
aGuard( maProtector
);
878 uno::Reference
< XScannerManager
> xThis( this );
880 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= "TWAIN" )
881 throw ScannerException("Scanner does not exist", xThis
, ScanError_InvalidContext
);
885 return aTwain
.SelectSource( *this );
888 void SAL_CALL
ScannerManager::startScan( const ScannerContext
& rContext
, const uno::Reference
< lang::XEventListener
>& rxListener
)
889 throw( ScannerException
)
891 osl::MutexGuard
aGuard( maProtector
);
892 uno::Reference
< XScannerManager
> xThis( this );
894 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= "TWAIN" )
895 throw ScannerException("Scanner does not exist", xThis
, ScanError_InvalidContext
);
898 aTwain
.PerformTransfer( *this, rxListener
);
901 ScanError SAL_CALL
ScannerManager::getError( const ScannerContext
& rContext
)
902 throw( ScannerException
)
904 osl::MutexGuard
aGuard( maProtector
);
905 uno::Reference
< XScannerManager
> xThis( this );
907 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= "TWAIN" )
908 throw ScannerException("Scanner does not exist", xThis
, ScanError_InvalidContext
);
910 return( ( aTwain
.GetState() == TWAIN_STATE_CANCELED
) ? ScanError_ScanCanceled
: ScanError_ScanErrorNone
);
913 uno::Reference
< awt::XBitmap
> SAL_CALL
ScannerManager::getBitmap( const ScannerContext
& /*rContext*/ )
914 throw( ScannerException
)
916 osl::MutexGuard
aGuard( maProtector
);
917 return uno::Reference
< awt::XBitmap
>( this );
920 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */