Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1151 lines
34 KiB

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORP., 2000
*
* TITLE: IStiUSD.cpp
*
* VERSION: 1.0
*
* DATE: 18 July, 2000
*
* DESCRIPTION:
* Implementation of the WIA sample scanner IStiUSD methods.
*
*******************************************************************************/
#include "pch.h"
extern HINSTANCE g_hInst; // used for WIAS_LOGPROC macro
#define THREAD_TERMINATION_TIMEOUT 10000
VOID EventThread( LPVOID lpParameter ); // event thread
/**************************************************************************\
* CWIAScannerDevice::CWIAScannerDevice
*
* Device class constructor
*
* Arguments:
*
* None
*
* Return Value:
*
* None
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
CWIAScannerDevice::CWIAScannerDevice(LPUNKNOWN punkOuter):
m_cRef(1),
m_fValid(FALSE),
m_punkOuter(NULL),
m_pIStiDevControl(NULL),
m_bUsdLoadEvent(FALSE),
m_dwLastOperationError(0),
m_dwLockTimeout(100),
m_hSignalEvent(NULL),
m_hShutdownEvent(NULL),
m_hEventNotifyThread(NULL),
m_guidLastEvent(GUID_NULL),
m_bstrDeviceID(NULL),
m_bstrRootFullItemName(NULL),
m_pIWiaEventCallback(NULL),
m_pIDrvItemRoot(NULL),
m_pStiDevice(NULL),
m_hInstance(NULL),
m_pIWiaLog(NULL),
m_NumSupportedFormats(0),
m_NumCapabilities(0),
m_NumSupportedTYMED(0),
m_NumInitialFormats(0),
m_NumSupportedDataTypes(0),
m_NumSupportedIntents(0),
m_NumSupportedCompressionTypes(0),
m_NumSupportedResolutions(0),
m_pSupportedFormats(NULL),
m_pInitialFormats(NULL),
m_pCapabilities(NULL),
m_pSupportedTYMED(NULL),
m_pSupportedDataTypes(NULL),
m_pSupportedIntents(NULL),
m_pSupportedCompressionTypes(NULL),
m_pSupportedResolutions(NULL),
m_pSupportedPreviewModes(NULL),
m_pszRootItemDefaults(NULL),
m_piRootItemDefaults(NULL),
m_pvRootItemDefaults(NULL),
m_psRootItemDefaults(NULL),
m_wpiRootItemDefaults(NULL),
m_pszItemDefaults(NULL),
m_piItemDefaults(NULL),
m_pvItemDefaults(NULL),
m_psItemDefaults(NULL),
m_wpiItemDefaults(NULL),
m_NumRootItemProperties(0),
m_NumItemProperties(0),
m_MaxBufferSize(65535),
m_MinBufferSize(65535),
m_bDeviceLocked(FALSE),
m_DeviceDefaultDataHandle(NULL),
m_bLegacyBWRestriction(FALSE),
m_pszDeviceNameA(NULL),
m_pScanAPI(NULL)
{
// See if we are aggregated. If we are (almost always the case) save
// pointer to the controlling Unknown , so subsequent calls will be
// delegated. If not, set the same pointer to "this".
if (punkOuter) {
m_punkOuter = punkOuter;
} else {
// Cast below is needed in order to point to right virtual table
m_punkOuter = reinterpret_cast<IUnknown*>
(static_cast<INonDelegatingUnknown*>
(this));
}
}
/**************************************************************************\
* CWIAScannerDevice::PrivateInitialize
*
* Device class private initialization code
*
* Arguments:
*
* None
*
* Return Value:
*
* HRESULT
*
\**************************************************************************/
HRESULT CWIAScannerDevice::PrivateInitialize()
{
HRESULT hr = S_OK;
#ifdef USE_SERVICE_LOG_CREATION
hr = wiasCreateLogInstance(g_hInst, &m_pIWiaLog);
#else
hr = CoCreateInstance(CLSID_WiaLog, NULL, CLSCTX_INPROC_SERVER,
IID_IWiaLog,(void**)&m_pIWiaLog);
if (SUCCEEDED(hr)) {
m_pIWiaLog->InitializeLog((LONG)(LONG_PTR)g_hInst);
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL1,("Logging COM object created successfully for wiafbdrv.dll"));
} else {
#ifdef DEBUG
OutputDebugString(TEXT("Could not CoCreateInstance on Logging COM object for wiafbdrv.dll, because we are STI only\n"));
OutputDebugString(TEXT("********* (Device must have been created for STI only) *********\n"));
#endif
hr = S_OK;
}
#endif
__try {
if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown, MINLONG)) {
hr = HRESULT_FROM_WIN32(::GetLastError());
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::PrivateInitialize, create shutdown critsect failed"));
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
hr = E_OUTOFMEMORY;
}
if(hr == S_OK) {
// Create event for syncronization of notifications shutdown.
m_hShutdownEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
if (m_hShutdownEvent && (INVALID_HANDLE_VALUE != m_hShutdownEvent)) {
m_fValid = TRUE;
} else {
hr = HRESULT_FROM_WIN32(::GetLastError());
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::PrivateInitialize, create shutdown event failed"));
}
}
return hr;
}
/**************************************************************************\
* CWIAScannerDevice::~CWIAScannerDevice
*
* Device class destructor
*
* Arguments:
*
* None
*
* Return Value:
*
* None
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
CWIAScannerDevice::~CWIAScannerDevice(void)
{
if(m_pScanAPI)
m_pScanAPI->UnInitialize();
// Kill notification thread if it exists.
SetNotificationHandle(NULL);
// Close event for syncronization of notifications shutdown.
if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
CloseHandle(m_hShutdownEvent);
m_hShutdownEvent = NULL;
}
// Release the device control interface.
if (m_pIStiDevControl) {
m_pIStiDevControl->Release();
m_pIStiDevControl = NULL;
}
//
// WIA member destruction
//
// Tear down the driver item tree.
if (m_pIDrvItemRoot) {
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIAScannerDevice, Deleting Device Item Tree (this is OK)"));
DeleteItemTree();
m_pIDrvItemRoot = NULL;
}
// free any IO handles opened
if(m_DeviceDefaultDataHandle){
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("~CWIAScannerDevice, Closing DefaultDeviceDataHandle"));
CloseHandle(m_DeviceDefaultDataHandle);
m_DeviceDefaultDataHandle = NULL;
}
// Cleanup the WIA event sink.
if (m_pIWiaEventCallback) {
m_pIWiaEventCallback->Release();
m_pIWiaEventCallback = NULL;
}
// Free the storage for the device ID.
if (m_bstrDeviceID) {
SysFreeString(m_bstrDeviceID);
m_bstrDeviceID = NULL;
}
// Release the objects supporting device property storage.
if (m_bstrRootFullItemName) {
SysFreeString(m_bstrRootFullItemName);
m_bstrRootFullItemName = NULL;
}
// Delete allocated arrays
DeleteCapabilitiesArrayContents();
DeleteSupportedIntentsArrayContents();
// Free the critical section.
DeleteCriticalSection(&m_csShutdown);
if(m_pIWiaLog)
m_pIWiaLog->Release();
if(m_pScanAPI)
delete m_pScanAPI;
}
/**************************************************************************\
* CWIAScannerDevice::GetCapabilities
*
* Get the device STI capabilities.
*
* Arguments:
*
* pUsdCaps - Pointer to USD capabilities data.
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::GetCapabilities");
memset(pUsdCaps, 0, sizeof(STI_USD_CAPS));
pUsdCaps->dwVersion = STI_VERSION;
pUsdCaps->dwGenericCaps = STI_USD_GENCAP_NATIVE_PUSHSUPPORT|
STI_GENCAP_NOTIFICATIONS |
STI_GENCAP_POLLING_NEEDED;
return STI_OK;
}
/**************************************************************************\
* CWIAScannerDevice::GetStatus
*
* Query device online and/or event status.
*
* Arguments:
*
* pDevStatus - Pointer to device status data.
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::GetStatus(PSTI_DEVICE_STATUS pDevStatus)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::GetStatus");
HRESULT hr = S_OK;
// Validate parameters.
if (!pDevStatus) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::GetStatus, NULL parameter"));
return E_INVALIDARG;
}
// If we are asked, verify the device is online.
if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE) {
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, WIA is asking the device if we are ONLINE"));
pDevStatus->dwOnlineState = 0L;
hr = m_pScanAPI->DeviceOnline();
if(SUCCEEDED(hr)){
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetStatus, Device is ONLINE"));
pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
} else {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetStatus, Device is OFFLINE"));
}
}
// If we are asked, verify state of event.
pDevStatus->dwEventHandlingState &= ~STI_EVENTHANDLING_PENDING;
if (pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE) {
// Generate an event the first time we load.
if (m_bUsdLoadEvent) {
pDevStatus->dwEventHandlingState = STI_EVENTHANDLING_PENDING;
m_guidLastEvent = guidEventFirstLoaded;
m_bUsdLoadEvent = FALSE;
}
// check for device events
hr = m_pScanAPI->GetDeviceEvent(&m_guidLastEvent);
if(SUCCEEDED(hr)){
if(m_guidLastEvent != GUID_NULL){
pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_PENDING;
}
}
}
return STI_OK;
}
/**************************************************************************\
* CWIAScannerDevice::DeviceReset
*
* Reset device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::DeviceReset(void)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::DeviceReset");
return m_pScanAPI->ResetDevice();
}
/**************************************************************************\
* CWIAScannerDevice::Diagnostic
*
* The test device always passes the diagnostic.
*
* Arguments:
*
* pBuffer - Pointer o diagnostic result data.
*
* Return Value:
*
* None
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::Diagnostic(LPSTI_DIAG pBuffer)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::Diagnostic");
// Initialize response buffer
memset(&pBuffer->sErrorInfo,0,sizeof(pBuffer->sErrorInfo));
pBuffer->dwStatusMask = 0;
pBuffer->sErrorInfo.dwGenericError = NOERROR;
pBuffer->sErrorInfo.dwVendorError = 0;
return m_pScanAPI->Diagnostic();
}
/**************************************************************************\
* CWIAScannerDevice::SetNotificationHandle
*
* Starts and stops the event notification thread.
*
* Arguments:
*
* hEvent - If not valid start the notification thread otherwise kill
* the notification thread.
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::SetNotificationHandle(HANDLE hEvent)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::SetNotificationHandle");
HRESULT hr = STI_OK;
EnterCriticalSection(&m_csShutdown);
// Are we starting or stopping the notification thread?
if (hEvent && (hEvent != INVALID_HANDLE_VALUE)) {
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, hEvent = %d",hEvent));
m_hSignalEvent = hEvent;
m_guidLastEvent = GUID_NULL;
if (NULL == m_hEventNotifyThread) {
DWORD dwThread = 0;
m_hEventNotifyThread = ::CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)EventThread,
(LPVOID)this,
0,
&dwThread);
if (!m_hEventNotifyThread) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("FlatbedScannerUsdDevice::SetNotificationHandle, CreateThread failed"));
hr = STIERR_UNSUPPORTED;
}
}
} else {
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Disabling event Notifications"));
// Disable event notifications.
if (m_hShutdownEvent && (m_hShutdownEvent != INVALID_HANDLE_VALUE)) {
if (!SetEvent(m_hShutdownEvent)) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Setting Shutdown event failed.."));
} else {
//
// WAIT for thread to terminate, only if the m_hEventNotifyThread is not NULL
//
if (NULL != m_hEventNotifyThread) {
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Waiting for Event Thread to terminate (%d ms timeout)",THREAD_TERMINATION_TIMEOUT));
DWORD dwResult = WaitForSingleObject(m_hEventNotifyThread,THREAD_TERMINATION_TIMEOUT);
switch (dwResult) {
case WAIT_TIMEOUT:
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread termination TIMED OUT!"));
break;
case WAIT_OBJECT_0:
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, We are signaled...YAY!"));
break;
case WAIT_ABANDONED:
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Event Thread was abandoned.."));
break;
default:
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, Unknown signal (%d) received from WaitForSingleObject() call",dwResult));
break;
}
}
//
// Close event for syncronization of notifications shutdown.
//
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SetNotificationHandle, Closing m_hShutdownEvent handle (it has been signaled)"));
CloseHandle(m_hShutdownEvent);
m_hShutdownEvent = NULL;
}
}
//
// terminate thread
//
if (NULL != m_hEventNotifyThread) {
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SetNotificationHandle, closing event Notifications thread handle"));
CloseHandle(m_hEventNotifyThread);
m_hEventNotifyThread = NULL;
}
m_guidLastEvent = GUID_NULL;
}
LeaveCriticalSection(&m_csShutdown);
return hr;
}
/**************************************************************************\
* CWIAScannerDevice::GetNotificationData
*
* Provides data on an event.
*
* Arguments:
*
* pBuffer - Pointer to event data.
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::GetNotificationData( LPSTINOTIFY pBuffer )
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::GetNotificationData");
// If we have notification ready - return it's guid
if (!IsEqualIID(m_guidLastEvent, GUID_NULL)) {
memset(&pBuffer->abNotificationData,0,sizeof(pBuffer->abNotificationData));
pBuffer->dwSize = sizeof(STINOTIFY);
pBuffer->guidNotificationCode = m_guidLastEvent;
m_guidLastEvent = GUID_NULL;
} else {
return STIERR_NOEVENTS;
}
return STI_OK;
}
/**************************************************************************\
* CWIAScannerDevice::Escape
*
* Issue a command to the device.
*
* Arguments:
*
* EscapeFunction - Command to be issued.
* pInData - Input data to be passed with command.
* cbInDataSize - Size of input data.
* pOutData - Output data to be passed back from command.
* cbOutDataSize - Size of output data buffer.
* pcbActualData - Size of output data actually written.
*
* Return Value:
*
* None
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::Escape(
STI_RAW_CONTROL_CODE EscapeFunction,
LPVOID pInData,
DWORD cbInDataSize,
LPVOID pOutData,
DWORD cbOutDataSize,
LPDWORD pcbActualData)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::Escape");
// Write command to device if needed.
return STIERR_UNSUPPORTED;
}
/**************************************************************************\
* CWIAScannerDevice::GetLastError
*
* Get the last error from the device.
*
* Arguments:
*
* pdwLastDeviceError - Pointer to last error data.
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::GetLastError(LPDWORD pdwLastDeviceError)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::GetLastError");
if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD))) {
return STIERR_INVALID_PARAM;
}
*pdwLastDeviceError = m_dwLastOperationError;
return STI_OK;
}
/**************************************************************************\
* CWIAScannerDevice::GetLastErrorInfo
*
* Get extended error information from the device.
*
* Arguments:
*
* pLastErrorInfo - Pointer to extended device error data.
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::GetLastErrorInfo");
if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
return STIERR_INVALID_PARAM;
}
pLastErrorInfo->dwGenericError = m_dwLastOperationError;
pLastErrorInfo->szExtendedErrorText[0] = '\0';
return STI_OK;
}
/**************************************************************************\
* CWIAScannerDevice::LockDevice
*
* Lock access to the device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::LockDevice(void)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::LockDevice");
HRESULT hr = STI_OK;
if(m_bDeviceLocked){
WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("LockDevice, Device is already locked!!"));
hr = STIERR_DEVICE_LOCKED;
} else {
m_bDeviceLocked = TRUE;
WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("LockDevice, Locking Device successful"));
}
return hr;
}
/**************************************************************************\
* CWIAScannerDevice::UnLockDevice
*
* Unlock access to the device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::UnLockDevice(void)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::UnLockDevice");
HRESULT hr = STI_OK;
if(!m_bDeviceLocked)
hr = STIERR_NEEDS_LOCK;
else {
m_bDeviceLocked = FALSE;
}
return hr;
}
/**************************************************************************\
* CWIAScannerDevice::RawReadData
*
* Read raw data from the device.
*
* Arguments:
*
* lpBuffer - buffer for returned data
* lpdwNumberOfBytes - number of bytes to read/returned
* lpOverlapped - overlap
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::RawReadData(
LPVOID lpBuffer,
LPDWORD lpdwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::RawReadData");
HRESULT hr = STI_OK;
BOOL fRet = FALSE;
DWORD dwBytesReturned = 0;
if (INVALID_HANDLE_VALUE != m_DeviceDefaultDataHandle) {
fRet = ReadFile( m_DeviceDefaultDataHandle,
lpBuffer,
*lpdwNumberOfBytes,
&dwBytesReturned,
lpOverlapped );
m_dwLastOperationError = ::GetLastError();
hr = fRet ? STI_OK : HRESULT_FROM_WIN32(m_dwLastOperationError);
*lpdwNumberOfBytes = (fRet) ? dwBytesReturned : 0;
} else {
hr = STIERR_NOT_INITIALIZED;
}
return hr;
}
/**************************************************************************\
* CWIAScannerDevice::RawWriteData
*
* Write raw data to the device.
*
* Arguments:
*
* lpBuffer - buffer for returned data
* dwNumberOfBytes - number of bytes to write
* lpOverlapped - overlap
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::RawWriteData(
LPVOID lpBuffer,
DWORD dwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::RawWriteData");
HRESULT hr = STI_OK;
BOOL fRet = FALSE;
DWORD dwBytesReturned = 0;
if (INVALID_HANDLE_VALUE != m_DeviceDefaultDataHandle) {
fRet = WriteFile(m_DeviceDefaultDataHandle,lpBuffer,dwNumberOfBytes,&dwBytesReturned,lpOverlapped);
m_dwLastOperationError = ::GetLastError();
hr = fRet ? STI_OK : HRESULT_FROM_WIN32(m_dwLastOperationError);
} else {
hr = STIERR_NOT_INITIALIZED;
}
return STI_OK;
}
/**************************************************************************\
* CWIAScannerDevice::RawReadCommand
*
*
*
* Arguments:
*
* lpBuffer - buffer for returned data
* lpdwNumberOfBytes - number of bytes to read/returned
* lpOverlapped - overlap
*
* Return Value:
*
* Status
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::RawReadCommand(
LPVOID lpBuffer,
LPDWORD lpdwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::RawReadCommand");
return STIERR_UNSUPPORTED;
}
/**************************************************************************\
* CWIAScannerDevice::RawWriteCommand
*
*
*
* Arguments:
*
* lpBuffer - buffer for returned data
* nNumberOfBytes - number of bytes to write
* lpOverlapped - overlap
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::RawWriteCommand(
LPVOID lpBuffer,
DWORD nNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::RawWriteCommand");
return STIERR_UNSUPPORTED;
}
/**************************************************************************\
* CWIAScannerDevice::Initialize
*
* Initialize the device object.
*
* Arguments:
*
* pIStiDevControlNone - device interface
* dwStiVersion - STI version
* hParametersKey - HKEY for registry reading/writing
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
STDMETHODIMP CWIAScannerDevice::Initialize(
PSTIDEVICECONTROL pIStiDevControl,
DWORD dwStiVersion,
HKEY hParametersKey)
{
CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"CWIAScannerDevice::Initialize");
HRESULT hr = STI_OK;
WCHAR szDeviceNameW[255];
TCHAR szGSDName[255];
TCHAR szMICRO[255];
TCHAR szResolutions[255];
UINT uiNameLen = 0;
INITINFO InitInfo;
memset(&InitInfo,0,sizeof(InitInfo));
if (!pIStiDevControl) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, invalid device control interface"));
return STIERR_INVALID_PARAM;
}
// Cache the device control interface.
m_pIStiDevControl = pIStiDevControl;
m_pIStiDevControl->AddRef();
//
// Get the name of the device port
//
hr = m_pIStiDevControl->GetMyDevicePortName(szDeviceNameW,sizeof(szDeviceNameW)/sizeof(WCHAR));
if (!SUCCEEDED(hr) || !*szDeviceNameW) {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, couldn't get device port"));
return hr;
}
uiNameLen = WideCharToMultiByte(CP_ACP, 0, szDeviceNameW, -1, NULL, NULL, 0, 0);
if (!uiNameLen) {
return STIERR_INVALID_PARAM;
}
m_pszDeviceNameA = new CHAR[uiNameLen+1];
if (!m_pszDeviceNameA) {
return STIERR_INVALID_PARAM;
}
WideCharToMultiByte(CP_ACP, 0, szDeviceNameW, -1, m_pszDeviceNameA, uiNameLen, 0, 0);
//
// Open kernel mode device driver.
//
m_DeviceDefaultDataHandle = CreateFileA(m_pszDeviceNameA,
GENERIC_READ | GENERIC_WRITE, // Access mask
0, // Share mode
NULL, // SA
OPEN_EXISTING, // Create disposition
FILE_ATTRIBUTE_SYSTEM, // Attributes
NULL );
m_dwLastOperationError = ::GetLastError();
hr = (m_DeviceDefaultDataHandle != INVALID_HANDLE_VALUE) ?
S_OK : MAKE_HRESULT(SEVERITY_ERROR,FACILITY_WIN32,m_dwLastOperationError);
if (FAILED(hr)) {
return hr;
}
InitInfo.hDeviceDataHandle = m_DeviceDefaultDataHandle;
InitInfo.szCreateFileName = m_pszDeviceNameA;
//
// Open DeviceData section to read driver specific information
//
HKEY hKey = hParametersKey;
HKEY hOpenKey = NULL;
if (RegOpenKeyEx(hKey, // handle to open key
TEXT("DeviceData"), // address of name of subkey to open
0, // options (must be NULL)
KEY_QUERY_VALUE|KEY_READ, // just want to QUERY a value
&hOpenKey // address of handle to open key
) == ERROR_SUCCESS) {
DWORD dwWritten = sizeof(DWORD);
DWORD dwType = REG_DWORD;
/////////////////////////////////////////////////////////////////////////////
// legacy MicroDriver registry entries, for BW scanners //
/////////////////////////////////////////////////////////////////////////////
LONG lNoColor = 0;
RegQueryValueEx(hOpenKey,
TEXT("NoColor"),
NULL,
&dwType,
(LPBYTE)&lNoColor,
&dwWritten);
if (lNoColor == 1) {
m_bLegacyBWRestriction = TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Micro driver registry entries, for ***mcro.dll loading //
/////////////////////////////////////////////////////////////////////////////
dwWritten = sizeof(szMICRO);
dwType = REG_SZ;
ZeroMemory(szMICRO,sizeof(szMICRO));
//
// Read Micro driver name
//
if (RegQueryValueEx(hOpenKey,
TEXT("MicroDriver"),
NULL,
&dwType,
(LPBYTE)szMICRO,
&dwWritten) == ERROR_SUCCESS) {
m_pScanAPI = new CMicroDriverAPI;
InitInfo.szModuleFileName = szMICRO;
}
/////////////////////////////////////////////////////////////////////////////
// resolution registry entries, for micro driver resolution restrictions //
/////////////////////////////////////////////////////////////////////////////
dwWritten = sizeof(szResolutions);
dwType = REG_SZ;
ZeroMemory(szGSDName,sizeof(szResolutions));
if (RegQueryValueEx(hOpenKey,
TEXT("Resolutions"),
NULL,
&dwType,
(LPBYTE)szResolutions,
&dwWritten) == ERROR_SUCCESS) {
if(m_pScanAPI){
m_pScanAPI->SetResolutionRestrictionString(szResolutions);
}
}
RegCloseKey(hOpenKey);
} else {
WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CWIAScannerDevice::Initialize, couldn't open DeviceData KEY"));
return E_FAIL;
}
//
// give logging interface to SCANAPI object
// so it can log too! (shouldn't leave the little guys out. ;) )
//
m_pScanAPI->SetLoggingInterface(m_pIWiaLog);
// set the HKEY for micro driver's device section
InitInfo.hKEY = hParametersKey;
// initialize the micro driver
hr = m_pScanAPI->Initialize(&InitInfo);
return hr;
}
/**************************************************************************\
* CWIAScannerDevice::DoEventProcessing
*
* Process device events
*
* Arguments:
*
*
* Return Value:
*
* Status.
*
* History:
*
* 7/18/2000 Original Version
*
\**************************************************************************/
HRESULT CWIAScannerDevice::DoEventProcessing()
{
HRESULT hr = S_OK;
INTERRUPTEVENTINFO EventInfo;
EventInfo.phSignalEvent = &m_hSignalEvent;
EventInfo.hShutdownEvent = m_hShutdownEvent;
EventInfo.pguidEvent = &m_guidLastEvent;
EventInfo.szDeviceName = m_pszDeviceNameA;
hr = m_pScanAPI->DoInterruptEventThread(&EventInfo);
// close the thread handle, when the thread exits
CloseHandle(m_hEventNotifyThread);
m_hEventNotifyThread = NULL;
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
// THREADS SECTION //
////////////////////////////////////////////////////////////////////////////////////////
VOID EventThread( LPVOID lpParameter )
{
PWIASCANNERDEVICE pThisDevice = (PWIASCANNERDEVICE)lpParameter;
pThisDevice->DoEventProcessing();
}