|
|
/*******************************************************************************
* * (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(); }
|