mirror of https://github.com/tongzx/nt5src
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.
1343 lines
36 KiB
1343 lines
36 KiB
//------------------------------------------------------------------------------
|
|
// Copyright (c) 1999-2000 Microsoft Corporation.
|
|
//
|
|
// device.cpp
|
|
//
|
|
// Implement IrTran-P device methods.
|
|
//
|
|
// Author:
|
|
//
|
|
// EdwardR 12-Aug-1999 Modeled from code by ReedB.
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
#include <irthread.h>
|
|
|
|
#include "ircamera.h"
|
|
#include "resource.h"
|
|
#include "tcamprop.h"
|
|
|
|
// #include "/nt/private/windows/imagein/ui/uicommon/simstr.h"
|
|
// #include "/nt/private/windows/imagein/ui/inc/shellext.h"
|
|
|
|
extern HINSTANCE g_hInst;
|
|
extern DWORD EnableDisableIrCOMM( IN BOOL fDisable ); // irtranp\irtranp.cpp
|
|
|
|
DWORD WINAPI EventMonitorThread( IN void *pvIrUsdDevice ); // Forward Ref.
|
|
|
|
#define SZ_REG_KEY_INFRARED TEXT("Control Panel\\Infrared")
|
|
#define SZ_REG_KEY_IRTRANP TEXT("Control Panel\\Infrared\\IrTranP")
|
|
#define SZ_REG_DISABLE_IRCOMM TEXT("DisableIrCOMM")
|
|
|
|
HKEY g_hRegistryKey = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
// SignalWIA()
|
|
//
|
|
// Helper function used by the IrTran-P code to signal WIA that a new
|
|
// picture has arrived.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// pvIrUsdDevice -- Device object. IrTran-P only knows this as a void*.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD SignalWIA( IN char *pszPathPlusFileName,
|
|
IN void *pvIrUsdDevice )
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwStatus = 0;
|
|
IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
|
|
|
|
|
|
//
|
|
// First, add the new picture to the tree representing the images:
|
|
//
|
|
if (pIrUsdDevice && pIrUsdDevice->IsInitialized())
|
|
{
|
|
TCHAR *ptszPath;
|
|
TCHAR *ptszFileName;
|
|
|
|
#ifdef UNICODE
|
|
|
|
int iStatus;
|
|
WCHAR wszTemp[MAX_PATH];
|
|
|
|
iStatus = MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
pszPathPlusFileName,
|
|
-1, // Auto-calculate length...
|
|
wszTemp,
|
|
MAX_PATH);
|
|
|
|
ptszPath = wszTemp;
|
|
ptszFileName = wcsrchr(wszTemp,L'\\');
|
|
ptszFileName++;
|
|
|
|
#else
|
|
|
|
ptszPath = pszPathPlusFileName;
|
|
ptszFileName = strrchr(pszPathPlusFileName,'\\');
|
|
ptszFileName++;
|
|
|
|
#endif
|
|
|
|
IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
|
|
IWiaDrvItem *pNewImage;
|
|
|
|
hr = pIrUsdDevice->CreateItemFromFileName(
|
|
WiaItemTypeFile | WiaItemTypeImage,
|
|
ptszPath,
|
|
ptszFileName,
|
|
&pNewImage);
|
|
|
|
if (!FAILED(hr))
|
|
{
|
|
IWiaDrvItem *pDrvItemRoot = pIrUsdDevice->GetDrvItemRoot();
|
|
|
|
hr = pNewImage->AddItemToFolder(pDrvItemRoot);
|
|
|
|
pNewImage->Release();
|
|
}
|
|
else
|
|
{
|
|
WIAS_ERROR((g_hInst,"SignalWIA(): CreateItemFromFileName() Failed: %x",hr));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now, signal WIA:
|
|
//
|
|
if (pIrUsdDevice)
|
|
{
|
|
DWORD dwNewTime = GetTickCount();
|
|
DWORD dwDelta = dwNewTime - pIrUsdDevice->m_dwLastConnectTime;
|
|
|
|
if (dwDelta > RECONNECT_TIMEOUT)
|
|
{
|
|
pIrUsdDevice->m_guidLastEvent = WIA_EVENT_DEVICE_CONNECTED;
|
|
if (!SetEvent(pIrUsdDevice->m_hSignalEvent))
|
|
{
|
|
dwStatus = GetLastError();
|
|
WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pIrUsdDevice->m_guidLastEvent = WIA_EVENT_ITEM_CREATED;
|
|
if (!SetEvent(pIrUsdDevice->m_hSignalEvent))
|
|
{
|
|
dwStatus = GetLastError();
|
|
WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
|
|
}
|
|
}
|
|
|
|
pIrUsdDevice->m_dwLastConnectTime = dwNewTime;
|
|
}
|
|
else
|
|
{
|
|
WIAS_ERROR((g_hInst,"SignalWIA(): null pvIrUsdDevice object"));
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// Display IrCamera browser if it's not already up:
|
|
//
|
|
#if FALSE
|
|
HINSTANCE hInst = LoadLibrary(TEXT("WIASHEXT.DLL"));
|
|
if (hInst)
|
|
{
|
|
WIAMAKEFULLPIDLFORDEVICE pfn =
|
|
(WIAMAKEFULLPIDLFORDEVICE)GetProcAddress(hInst, "MakeFullPidlForDevice");
|
|
|
|
if (pfn)
|
|
{
|
|
LPITEMIDLIST pidl = NULL;
|
|
|
|
pfn( pIrUsdDevice->m_bstrDeviceID, &pidl );
|
|
|
|
if (pidl)
|
|
{
|
|
SHELLEXECUTEINFO sei;
|
|
|
|
memset( &sei, 0, sizeof(sei) );
|
|
|
|
sei.cbSize = sizeof(sei);
|
|
// sei.hwnd = hDlg;
|
|
sei.fMask = SEE_MASK_IDLIST;
|
|
sei.nShow = SW_SHOW;
|
|
sei.lpIDList = pidl;
|
|
|
|
ShellExecuteEx( &sei );
|
|
|
|
LPMALLOC pMalloc = NULL;
|
|
if (SUCCEEDED(SHGetMalloc(&pMalloc)) && pMalloc)
|
|
{
|
|
pMalloc->Free(pidl);
|
|
pMalloc->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FreeLibrary( hInst );
|
|
}
|
|
#endif
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::IrUsdDevice()
|
|
//
|
|
// Device class constructor
|
|
//
|
|
// Arguments:
|
|
//
|
|
// punkOuter
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
IrUsdDevice::IrUsdDevice( LPUNKNOWN punkOuter ):
|
|
m_cRef(1),
|
|
m_punkOuter(NULL),
|
|
m_dwLastConnectTime(0),
|
|
m_fValid(FALSE),
|
|
m_pIStiDevControl(NULL),
|
|
m_hShutdownEvent(INVALID_HANDLE_VALUE),
|
|
m_hRegistryEvent(INVALID_HANDLE_VALUE),
|
|
m_hSignalEvent(INVALID_HANDLE_VALUE),
|
|
m_hIrTranPThread(NULL),
|
|
m_hEventMonitorThread(NULL),
|
|
m_guidLastEvent(GUID_NULL),
|
|
m_pIWiaEventCallback(NULL),
|
|
m_pStiDevice(NULL),
|
|
m_bstrDeviceID(NULL),
|
|
m_bstrRootFullItemName(NULL),
|
|
m_pIDrvItemRoot(NULL)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::IrUsdDevice"));
|
|
|
|
//
|
|
// 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));
|
|
}
|
|
}
|
|
|
|
HRESULT IrUsdDevice::PrivateInitialize()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
__try {
|
|
if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown, MINLONG))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::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_ERROR((g_hInst,"IrUsdDevice::PrivateInitialize, create shutdown event failed"));
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// IrUsdDevice::~IrUsdDevice
|
|
//
|
|
// Device class destructor
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
//------------------------------------------------------------------------
|
|
IrUsdDevice::~IrUsdDevice(void)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::~IrUsdDevice"));
|
|
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
if (m_hRegistryEvent && (m_hRegistryEvent != INVALID_HANDLE_VALUE))
|
|
{
|
|
CloseHandle(m_hRegistryEvent);
|
|
}
|
|
|
|
//
|
|
// Release the device control interface.
|
|
//
|
|
|
|
if (m_pIStiDevControl)
|
|
{
|
|
m_pIStiDevControl->Release();
|
|
m_pIStiDevControl = NULL;
|
|
}
|
|
|
|
//
|
|
// WIA member destruction
|
|
//
|
|
// Cleanup the WIA event sink.
|
|
//
|
|
|
|
if (m_pIWiaEventCallback)
|
|
{
|
|
m_pIWiaEventCallback->Release();
|
|
}
|
|
|
|
//
|
|
// Free the storage for the device ID.
|
|
//
|
|
|
|
if (m_bstrDeviceID)
|
|
{
|
|
SysFreeString(m_bstrDeviceID);
|
|
}
|
|
|
|
//
|
|
// Release the objects supporting device property storage.
|
|
//
|
|
|
|
if (m_bstrRootFullItemName)
|
|
{
|
|
SysFreeString(m_bstrRootFullItemName);
|
|
}
|
|
|
|
//
|
|
// Free the critical section.
|
|
//
|
|
DeleteCriticalSection(&m_csShutdown);
|
|
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IrUsdDevice::GetCapabilities
|
|
*
|
|
* Get the device STI capabilities.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pUsdCaps - Pointer to USD capabilities data.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP IrUsdDevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
|
|
{
|
|
ZeroMemory(pUsdCaps, sizeof(*pUsdCaps));
|
|
|
|
pUsdCaps->dwVersion = STI_VERSION;
|
|
|
|
//
|
|
// We do support device notifications, but do not requiring polling.
|
|
//
|
|
|
|
pUsdCaps->dwGenericCaps = STI_USD_GENCAP_NATIVE_PUSHSUPPORT;
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::GetStatus()
|
|
//
|
|
// Query device online and/or event status.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// pDevStatus - Pointer to device status data.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STI_OK
|
|
// E_INVALIDARG
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::GetStatus( IN OUT PSTI_DEVICE_STATUS pDevStatus )
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::GetStatus()"));
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
if (!pDevStatus)
|
|
{
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::GetStatus, NULL device status"));
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// If we are asked, verify whether device is online.
|
|
//
|
|
pDevStatus->dwOnlineState = 0L;
|
|
if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE)
|
|
{
|
|
//
|
|
// The IrTran-P device is always on-line:
|
|
//
|
|
pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// event pending ???
|
|
//
|
|
}
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::DeviceReset()
|
|
//
|
|
// Reset data file pointer to start of file. For IrTran-P, we don't need
|
|
// to do anything.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STI_OK
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::DeviceReset(void)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::DeviceReset()"));
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::Diagnostic()
|
|
//
|
|
// Run the camera through a test diagnostic. The IrTran-P device will
|
|
// always pass the diagnostic.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// pBuffer - Pointer o diagnostic results data.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STI_OK
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::Diagnostic( IN OUT LPSTI_DIAG pBuffer )
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::Diagnostic()"));
|
|
|
|
//
|
|
// Initialize response buffer
|
|
//
|
|
pBuffer->dwStatusMask = 0;
|
|
|
|
memset( &pBuffer->sErrorInfo, 0, sizeof(pBuffer->sErrorInfo) );
|
|
|
|
pBuffer->sErrorInfo.dwGenericError = NOERROR;
|
|
pBuffer->sErrorInfo.dwVendorError = 0;
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::StartIrTranPThread()
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD IrUsdDevice::StartIrTranPThread()
|
|
{
|
|
DWORD dwStatus = S_OK;
|
|
DWORD dwThread;
|
|
|
|
if (!m_hIrTranPThread)
|
|
{
|
|
m_hIrTranPThread = CreateThread( NULL, // Default security
|
|
0, // Default stack size
|
|
IrTranP, // IrTran-P protocol eng.
|
|
(LPVOID)this,
|
|
0, // Creation flags
|
|
&dwThread); // New thread ID.
|
|
|
|
if (!m_hIrTranPThread)
|
|
{
|
|
dwStatus = ::GetLastError();
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): unable to create IrTran-P thread: %d",dwStatus));
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::StopIrTranPThread()
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD IrUsdDevice::StopIrTranPThread()
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
//
|
|
// Shutdown the listen on IrCOMM, this will cause the IrTran-P thread
|
|
// to exit.
|
|
//
|
|
dwStatus = EnableDisableIrCOMM(TRUE); // TRUE == Disable.
|
|
|
|
m_hIrTranPThread = NULL;
|
|
|
|
return dwStatus;
|
|
}
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::StartEventMonitorThread()
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD IrUsdDevice::StartEventMonitorThread()
|
|
{
|
|
DWORD dwStatus = S_OK;
|
|
DWORD dwThread;
|
|
|
|
//
|
|
// Event to signal for registry changes:
|
|
//
|
|
if ((!m_hRegistryEvent)||(m_hRegistryEvent == INVALID_HANDLE_VALUE))
|
|
{
|
|
m_hRegistryEvent = CreateEvent( NULL, // Security
|
|
FALSE, // Auto-reset
|
|
FALSE, // Initially not set
|
|
NULL ); // No name
|
|
}
|
|
|
|
if (!m_hRegistryEvent)
|
|
{
|
|
dwStatus = ::GetLastError();
|
|
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::StartEventMonitorThread(): unable to create Registry Monitor Event: %d",dwStatus));
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// Start monitoring the registry to look for enable/disable changes
|
|
// for access to the IrCOMM port.
|
|
//
|
|
if (!m_hEventMonitorThread)
|
|
{
|
|
m_hEventMonitorThread = CreateThread(
|
|
NULL, // Default security
|
|
0, // Default stack size
|
|
EventMonitorThread,
|
|
(LPVOID)this,// Function data
|
|
0, // Creation flags
|
|
&dwThread ); // New thread ID
|
|
if (!m_hEventMonitorThread)
|
|
{
|
|
dwStatus = ::GetLastError();
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::StartEventMonitorThread(): unable to create Registry Monitor Thread: %d",dwStatus));
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::SetNotificationHandle()
|
|
//
|
|
// Starts and stops the event notification thread.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// hEvent - Event to use in signaling WIA of events (like CONNECT etc.)
|
|
// If valid start the notification thread otherwise kill the
|
|
// notification thread.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STI_OK
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::SetNotificationHandle( IN HANDLE hEvent )
|
|
{
|
|
DWORD dwStatus;
|
|
HRESULT hr = STI_OK;
|
|
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle"));
|
|
|
|
|
|
EnterCriticalSection(&m_csShutdown);
|
|
|
|
//
|
|
// Are we starting or stopping the notification thread?
|
|
//
|
|
if (hEvent && (hEvent != INVALID_HANDLE_VALUE))
|
|
{
|
|
m_hSignalEvent = hEvent;
|
|
|
|
//
|
|
// Initialize to no event.
|
|
//
|
|
m_guidLastEvent = GUID_NULL;
|
|
|
|
#if FALSE
|
|
//
|
|
// Create the notification thread.
|
|
//
|
|
if (!m_hIrTranPThread)
|
|
{
|
|
DWORD dwThread;
|
|
|
|
m_hIrTranPThread = CreateThread(
|
|
NULL, // Default security
|
|
0, // Default stack size
|
|
IrTranP, // IrTran-P protocol eng.
|
|
(LPVOID)this,
|
|
0, // Creation flags
|
|
&dwThread); // New thread ID.
|
|
|
|
if (m_hIrTranPThread)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle(): Enabling IrTran-P"));
|
|
}
|
|
else
|
|
{
|
|
dwStatus = ::GetLastError();
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): unable to create IrTran-P thread: %d",dwStatus));
|
|
hr = HRESULT_FROM_WIN32(dwStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::SetNotificationHandle(): spurious IrTran-P thread"));
|
|
hr = STI_OK; // STIERR_UNSUPPORTED;
|
|
}
|
|
#endif
|
|
|
|
dwStatus = StartEventMonitorThread();
|
|
|
|
if (dwStatus)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable event notifications.
|
|
//
|
|
SetEvent(m_hShutdownEvent);
|
|
|
|
if (m_hIrTranPThread)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::SetNotificationHandle(): stopping IrTran-P thread"));
|
|
UninitializeIrTranP(m_hIrTranPThread);
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_csShutdown);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::GetNotificationData()
|
|
//
|
|
// WIA calls this function to get data on the event. Currently for IrTran-P,
|
|
// we get one of two events either WIA_EVENT_DEVICE_CONNECTED or
|
|
// WIA_EVENT_ITEM_CREATED.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// pStiNotify - Pointer to event data.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STI_OK
|
|
// STIERR_NOEVENT (not currently returned).
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::GetNotificationData( IN OUT LPSTINOTIFY pStiNotify )
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::GetNotificationData()"));
|
|
|
|
memset(pStiNotify,0,sizeof(STINOTIFY));
|
|
|
|
pStiNotify->dwSize = sizeof(STINOTIFY);
|
|
|
|
pStiNotify->guidNotificationCode = m_guidLastEvent;
|
|
|
|
//
|
|
// If we are to return a device connected then follow it by an item
|
|
// created event.
|
|
//
|
|
if (IsEqualGUID(m_guidLastEvent,WIA_EVENT_DEVICE_CONNECTED))
|
|
{
|
|
m_guidLastEvent = WIA_EVENT_ITEM_CREATED;
|
|
if (!SetEvent(m_hSignalEvent))
|
|
{
|
|
dwStatus = ::GetLastError();
|
|
WIAS_ERROR((g_hInst,"SignalWIA(): SetEvent() Failed: %d",dwStatus));
|
|
}
|
|
}
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::Escape()
|
|
//
|
|
// Used to issue a command to the device. IrTran-P doesn't support this.
|
|
//
|
|
// 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:
|
|
//
|
|
// HRESULT - STI_OK
|
|
// STIERR_UNSUPPORTED
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::Escape(
|
|
STI_RAW_CONTROL_CODE EscapeFunction,
|
|
LPVOID pInData,
|
|
DWORD cbInDataSize,
|
|
LPVOID pOutData,
|
|
DWORD cbOutDataSize,
|
|
LPDWORD pcbActualData )
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::Escape(): unsupported"));
|
|
|
|
//
|
|
// Write command to device if needed.
|
|
//
|
|
|
|
return STIERR_UNSUPPORTED;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::GetLastError()
|
|
//
|
|
// Get the last error from the device.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// pdwLastDeviceError - Pointer to last error data.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STI_OK
|
|
// STIERR_INVALID_PARAM
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::GetLastError( OUT LPDWORD pdwLastDeviceError )
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::GetLastError()"));
|
|
|
|
if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD)))
|
|
{
|
|
return STIERR_INVALID_PARAM;
|
|
}
|
|
|
|
*pdwLastDeviceError = m_dwLastOperationError;
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IrUsdDevice::GetLastErrorInfo
|
|
*
|
|
* Get extended error information from the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pLastErrorInfo - Pointer to extended device error data.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP IrUsdDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::GetLastErrorInfo"));
|
|
|
|
if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
|
|
return STIERR_INVALID_PARAM;
|
|
}
|
|
|
|
pLastErrorInfo->dwGenericError = m_dwLastOperationError;
|
|
pLastErrorInfo->szExtendedErrorText[0] = '\0';
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IrUsdDevice::LockDevice
|
|
*
|
|
* Lock access to the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP IrUsdDevice::LockDevice(void)
|
|
{
|
|
return STI_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IrUsdDevice::UnLockDevice
|
|
*
|
|
* Unlock access to the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP IrUsdDevice::UnLockDevice(void)
|
|
{
|
|
return STI_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IrUsdDevice::RawReadData
|
|
*
|
|
* Read raw data from the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lpBuffer -
|
|
* lpdwNumberOfBytes -
|
|
* lpOverlapped -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP IrUsdDevice::RawReadData(
|
|
LPVOID lpBuffer,
|
|
LPDWORD lpdwNumberOfBytes,
|
|
LPOVERLAPPED lpOverlapped)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RawReadData"));
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* IrUsdDevice::RawWriteData
|
|
*
|
|
* Write raw data to the device.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* lpBuffer -
|
|
* dwNumberOfBytes -
|
|
* lpOverlapped -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status.
|
|
*
|
|
* History:
|
|
*
|
|
* 9/11/1998 Original Version
|
|
*
|
|
\**************************************************************************/
|
|
|
|
STDMETHODIMP IrUsdDevice::RawWriteData(
|
|
LPVOID lpBuffer,
|
|
DWORD dwNumberOfBytes,
|
|
LPOVERLAPPED lpOverlapped)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RawWriteData"));
|
|
|
|
return STI_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::RawReadCommand()
|
|
//
|
|
// Raw read of bytes directly from the camera. Not supported by IrTran-P
|
|
// device.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// lpBuffer -
|
|
// lpdwNumberOfBytes -
|
|
// lpOverlapped -
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STIERR_UNSUPPORTED
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::RawReadCommand(
|
|
IN LPVOID lpBuffer,
|
|
IN LPDWORD lpdwNumberOfBytes,
|
|
IN LPOVERLAPPED lpOverlapped)
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RawReadCommand() not supported"));
|
|
|
|
return STIERR_UNSUPPORTED;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::RawWriteCommand()
|
|
//
|
|
// Raw write of byte directly to a camera. Not supported by IrTran-P device.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// lpBuffer -
|
|
// nNumberOfBytes -
|
|
// lpOverlapped -
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT - STIERR_UNSUPPORTED
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::RawWriteCommand(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD nNumberOfBytes,
|
|
IN LPOVERLAPPED lpOverlapped )
|
|
{
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RawWriteCommand(): not supported"));
|
|
|
|
return STIERR_UNSUPPORTED;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::Initialize()
|
|
//
|
|
// Initialize the device object.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// pIStiDevControlNone -
|
|
// dwStiVersion -
|
|
// hParametersKey -
|
|
//
|
|
// Return Value:
|
|
//
|
|
// HRESULT STI_OK
|
|
// STIERR_INVALID_PARAM
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP IrUsdDevice::Initialize(
|
|
PSTIDEVICECONTROL pIStiDevControl,
|
|
DWORD dwStiVersion,
|
|
HKEY hParametersKey )
|
|
{
|
|
HRESULT hr = STI_OK;
|
|
UINT uiNameLen = 0;
|
|
CAMERA_STATUS camStatus;
|
|
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::Initialize"));
|
|
|
|
if (!pIStiDevControl)
|
|
{
|
|
WIAS_ERROR((g_hInst,"IrUsdDevice::Initialize(): invalid device control interface"));
|
|
return STIERR_INVALID_PARAM;
|
|
}
|
|
|
|
//
|
|
// Cache the device control interface:
|
|
//
|
|
m_pIStiDevControl = pIStiDevControl;
|
|
m_pIStiDevControl->AddRef();
|
|
|
|
//
|
|
// Try to open the camera only once here during Initialize:
|
|
//
|
|
hr = CamOpenCamera(&camStatus);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IrUsdDevice::RunNotifications()
|
|
//
|
|
// Monitor changes to the source data file parent directory.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// None
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
VOID IrUsdDevice::RunNotifications(void)
|
|
{
|
|
//
|
|
// Start up camera event dlg
|
|
//
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications: start up event dlg"));
|
|
|
|
HWND hWnd = GetDesktopWindow();
|
|
|
|
int iret = DialogBoxParam( g_hInst,
|
|
MAKEINTRESOURCE(IDD_EVENT_DLG),
|
|
hWnd,
|
|
CameraEventDlgProc,
|
|
(LPARAM)this );
|
|
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications, iret = 0x%lx",iret));
|
|
|
|
if (iret == -1)
|
|
{
|
|
DWORD dwStatus = ::GetLastError();
|
|
WIAS_TRACE((g_hInst,"IrUsdDevice::RunNotifications, dlg error = 0x%lx",dwStatus));
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// NotificationsThread()
|
|
//
|
|
// Calls RunNotifications() to put up a dialog to start events.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// lpParameter - Pointer to device object.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
VOID NotificationsThread( LPVOID lpParameter )
|
|
{
|
|
WIAS_TRACE((g_hInst,"NotificationsThread(): Start"));
|
|
|
|
IrUsdDevice *pThisDevice = (IrUsdDevice*)lpParameter;
|
|
|
|
pThisDevice->RunNotifications();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// OpenIrTranPKey()
|
|
//
|
|
// Open and return a registry handle to the IrTranP key in the registry.
|
|
// This key will be monitored for changes in value.
|
|
//--------------------------------------------------------------------------
|
|
DWORD OpenIrTranPKey( HKEY *phRegistryKey )
|
|
{
|
|
DWORD dwStatus = 0;
|
|
DWORD dwDisposition = 0;
|
|
HKEY hKey;
|
|
|
|
*phRegistryKey = 0;
|
|
|
|
//
|
|
// If we've been called before, then we don't need to reopen the key.
|
|
//
|
|
if (g_hRegistryKey)
|
|
{
|
|
*phRegistryKey = g_hRegistryKey;
|
|
return 0;
|
|
}
|
|
|
|
if (RegCreateKeyEx(HKEY_CURRENT_USER,
|
|
SZ_REG_KEY_INFRARED,
|
|
0, // reserved MBZ
|
|
0, // class name
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0, // security attributes
|
|
&hKey,
|
|
&dwDisposition))
|
|
{
|
|
// Create failed.
|
|
dwStatus = GetLastError();
|
|
WIAS_TRACE((g_hInst,"OpenIrTranPKey(): RegCreateKeyEx(): '%' failed %d", SZ_REG_KEY_INFRARED, dwStatus));
|
|
}
|
|
|
|
if (RegCloseKey(hKey))
|
|
{
|
|
// Close failed.
|
|
}
|
|
|
|
if (RegCreateKeyEx(HKEY_CURRENT_USER,
|
|
SZ_REG_KEY_IRTRANP,
|
|
0, // reserved, MBZ
|
|
0, // class name
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey, // security attributes
|
|
&dwDisposition))
|
|
{
|
|
// Create failed
|
|
dwStatus = GetLastError();
|
|
WIAS_TRACE((g_hInst,"OpenIrTranPKey(): RegCreateKeyEx(): '%' failed %d", SZ_REG_KEY_IRTRANP, dwStatus));
|
|
}
|
|
|
|
*phRegistryKey = g_hRegistryKey = hKey;
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CheckForIrCOMMEnabled()
|
|
//
|
|
// Check the registry to see if IrCOMM for IrTran-P is enabled, if it is
|
|
// then return TRUE, else return FALSE.
|
|
//
|
|
// Note: Don't close the key, it is maintained globally and will be closed
|
|
// at shutdown.
|
|
//--------------------------------------------------------------------------
|
|
BOOL CheckForIrCOMMEnabled( IN IrUsdDevice *pIrUsdDevice )
|
|
{
|
|
DWORD dwStatus;
|
|
DWORD dwType;
|
|
DWORD dwDisabled;
|
|
DWORD dwValueSize = sizeof(dwDisabled);
|
|
HKEY hKey;
|
|
|
|
dwStatus = OpenIrTranPKey(&hKey);
|
|
if (dwStatus)
|
|
{
|
|
// If the key doesn't exist, or can't be opened, then assume that
|
|
// we are enabled...
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Check the value of the "DisableIrCOMM" value. Zero or missing value
|
|
// means fEnabled == TRUE, non-zero value means fEnabled == FALSE.
|
|
//
|
|
if (RegQueryValueEx( hKey, // IrTranP registry key
|
|
SZ_REG_DISABLE_IRCOMM,
|
|
NULL, // reserved, MB NULL
|
|
&dwType, // out, value type (expect: REG_DWORD)
|
|
(BYTE*)&dwDisabled, // out, value
|
|
&dwValueSize)) // in/out, size of value
|
|
{
|
|
// Query disabled flag registry value failed, assume enabled.
|
|
return TRUE;
|
|
}
|
|
|
|
if ((dwType == REG_DWORD) && (dwDisabled))
|
|
{
|
|
// Disabled flag is set.
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// EventMonitorThread()
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD WINAPI EventMonitorThread( IN void *pvIrUsdDevice )
|
|
{
|
|
DWORD dwStatus = 0;
|
|
BOOL fEnabled;
|
|
HANDLE hHandles[2];
|
|
HKEY hRegistryKey;
|
|
IrUsdDevice *pIrUsdDevice = (IrUsdDevice*)pvIrUsdDevice;
|
|
|
|
//
|
|
// Get the IrTranP registry key. We will monitor this key for
|
|
// changes...
|
|
//
|
|
dwStatus = OpenIrTranPKey(&hRegistryKey);
|
|
if (dwStatus)
|
|
{
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// We will Monitor two events. One for shutdown of the USD, the
|
|
// other for registry state changes (to enable/disable listen on
|
|
// IrCOMM).
|
|
//
|
|
hHandles[0] = pIrUsdDevice->m_hShutdownEvent;
|
|
hHandles[1] = pIrUsdDevice->m_hRegistryEvent;
|
|
|
|
while (TRUE)
|
|
{
|
|
fEnabled = CheckForIrCOMMEnabled(pIrUsdDevice);
|
|
|
|
if ((fEnabled) && (!pIrUsdDevice->m_hIrTranPThread))
|
|
{
|
|
// Start IrTran-P listen/protocol thread.
|
|
dwStatus = pIrUsdDevice->StartIrTranPThread();
|
|
}
|
|
else if (pIrUsdDevice->m_hIrTranPThread)
|
|
{
|
|
// Stop IrTran-P listen/protocol thread.
|
|
dwStatus = pIrUsdDevice->StopIrTranPThread();
|
|
}
|
|
|
|
dwStatus = RegNotifyChangeKeyValue( hRegistryKey, // IrTranP key
|
|
FALSE, // don't watch subtree
|
|
REG_NOTIFY_CHANGE_LAST_SET,
|
|
pIrUsdDevice->m_hRegistryEvent,
|
|
TRUE ); // Asynchronous
|
|
|
|
dwStatus = WaitForMultipleObjects( 2,
|
|
hHandles,
|
|
FALSE,
|
|
INFINITE);
|
|
if (dwStatus == WAIT_FAILED)
|
|
{
|
|
dwStatus = GetLastError();
|
|
break;
|
|
}
|
|
|
|
if (dwStatus == WAIT_OBJECT_0)
|
|
{
|
|
// Received a shutdown event. If the IrTranP thread is running
|
|
// then shut it down. Break out of this while loop to stop this
|
|
// monitor thread.
|
|
break;
|
|
}
|
|
|
|
if (dwStatus == WAIT_OBJECT_0+1)
|
|
{
|
|
// Received a registry change event. We'll continue around the
|
|
// while loop and check to see if IrTranP over IrCOMM has been
|
|
// disabled...
|
|
continue;
|
|
}
|
|
|
|
else if (dwStatus == WAIT_ABANDONED_0)
|
|
{
|
|
// Wait abandonded on the shutdown event
|
|
}
|
|
else if (dwStatus == WAIT_ABANDONED_0+1)
|
|
{
|
|
// Wait abandonded on the registry change event
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|