2025-04-27 07:49:33 -04:00

1061 lines
29 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORP., 1998
*
* TITLE: Device.Cpp
*
* VERSION: 2.0
*
* DATE: 5 Jan, 1999
*
* DESCRIPTION:
* Implementation of the WIA test scanner device methods. This sample WIA USD
* supports push events by detecting when %windir%\temp\TESTUSD.BMP file has
* been modified. This file becomes the new source of scanning data. An
* event is generated the first time the device is loaded.
*
*******************************************************************************/
#include <tchar.h>
#include "testusd.h"
extern HINSTANCE g_hInst;
extern IWiaLog *g_pIWiaLog;
// Function prototypes, implemented in this file:
void FileChangeThread(LPVOID lpParameter);
/**************************************************************************\
* TestUsdDevice::TestUsdDevice
*
* Device class constructor
*
* Arguments:
*
* None
*
* Return Value:
*
* None
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
TestUsdDevice::TestUsdDevice(LPUNKNOWN punkOuter):
m_cRef(1),
m_punkOuter(NULL),
m_fValid(FALSE),
m_pIStiDevControl(NULL),
m_hShutdownEvent(INVALID_HANDLE_VALUE),
m_hSignalEvent(INVALID_HANDLE_VALUE),
m_hEventNotifyThread(NULL),
m_guidLastEvent(GUID_NULL),
m_pIWiaEventCallback(NULL),
m_bstrDeviceID(NULL),
m_bstrRootFullItemName(NULL),
m_pStiDevice(NULL),
m_pIDrvItemRoot(NULL)
{
WIAS_LTRACE(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
("TestUsdDevice::TestUsdDevice (create)"));
*m_szSrcDataName = L'\0';
// 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));
}
}
/**************************************************************************\
* TestUsdDevice::PrivateInitialize
*
* Device class private initialization
*
* Arguments:
*
* None
*
* Return Value:
*
* HRESULT
*
\**************************************************************************/
HRESULT TestUsdDevice::PrivateInitialize()
{
HRESULT hr = S_OK;
__try {
if(!InitializeCriticalSectionAndSpinCount(&m_csShutdown)) {
hr = HRESULT_FROM_WIN32(::GetLastError());
}
}
__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(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::TestUsdDevice, create shutdown event failed"));
}
}
return hr;
}
/**************************************************************************\
* TestUsdDevice::~TestUsdDevice
*
* Device class destructor
*
* Arguments:
*
* None
*
* Return Value:
*
* None
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
TestUsdDevice::~TestUsdDevice(void)
{
WIAS_LTRACE(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
("TestUsdDevice::~TestUsdDevice (destroy)"));
// 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) {
DeleteItemTree();
m_pIDrvItemRoot = 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 strings used in the Capabilites array
DeleteCapabilitiesArrayContents();
// Free the critical section.
DeleteCriticalSection(&m_csShutdown);
}
/**************************************************************************\
* TestUsdDevice::GetCapabilities
*
* Get the device STI capabilities.
*
* Arguments:
*
* pUsdCaps - Pointer to USD capabilities data.
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::GetCapabilities");
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;
}
/**************************************************************************\
* TestUsdDevice::GetStatus
*
* Query device online and/or event status.
*
* Arguments:
*
* pDevStatus - Pointer to device status data.
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::GetStatus(PSTI_DEVICE_STATUS pDevStatus)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::GetStatus");
// Validate parameters.
if (!pDevStatus) {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::GetStatus, NULL parameter"));
return E_INVALIDARG;
}
// If we are asked, verify whether device is online.
pDevStatus->dwOnlineState = 0L;
if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE) {
// The test 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;
}
// Has there been a change in the source data file?
if (IsChangeDetected(NULL)) {
pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_PENDING;
}
}
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::DeviceReset
*
* Reset data file pointer to start of file.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::DeviceReset(void)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::DeviceReset");
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::Diagnostic
*
* The test device always passes the diagnostic.
*
* Arguments:
*
* pBuffer - Pointer o diagnostic result data.
*
* Return Value:
*
* None
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::Diagnostic(LPSTI_DIAG pBuffer)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::Diagnostic");
// Initialize response buffer
pBuffer->dwStatusMask = 0;
ZeroMemory(&pBuffer->sErrorInfo,sizeof(pBuffer->sErrorInfo));
pBuffer->sErrorInfo.dwGenericError = NOERROR;
pBuffer->sErrorInfo.dwVendorError = 0;
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::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:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::SetNotificationHandle(HANDLE hEvent)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::SetNotificationHandle");
HRESULT hr;
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;
// Create the notification thread.
if (!m_hEventNotifyThread) {
DWORD dwThread;
m_hEventNotifyThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)FileChangeThread,
(LPVOID)this,
0,
&dwThread);
if (!m_hEventNotifyThread) {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::SetNotificationHandle, unable to create notification thread"));
hr = HRESULT_FROM_WIN32(::GetLastError());
}
}
else {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::SetNotificationHandle, spurious notification thread"));
hr = STIERR_UNSUPPORTED;
}
}
else {
// Disable event notifications.
SetEvent(m_hShutdownEvent);
if (m_hEventNotifyThread) {
WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("Disabling event notification"));
WaitForSingleObject(m_hEventNotifyThread, 400);
CloseHandle(m_hEventNotifyThread);
m_hEventNotifyThread = NULL;
m_guidLastEvent = GUID_NULL;
}
}
LeaveCriticalSection(&m_csShutdown);
return hr;
}
/**************************************************************************\
* TestUsdDevice::GetNotificationData
*
* Provides data on n event.
*
* Arguments:
*
* pBuffer - Pointer to event data.
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::GetNotificationData( LPSTINOTIFY pBuffer )
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::GetNotificationData");
// If we have notification ready - return it's guid
if (!IsEqualIID(m_guidLastEvent, GUID_NULL)) {
pBuffer->guidNotificationCode = m_guidLastEvent;
m_guidLastEvent = GUID_NULL;
pBuffer->dwSize = sizeof(STINOTIFY);
ZeroMemory(&pBuffer->abNotificationData, sizeof(pBuffer->abNotificationData));
}
else {
return STIERR_NOEVENTS;
}
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::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:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::Escape(
STI_RAW_CONTROL_CODE EscapeFunction,
LPVOID pInData,
DWORD cbInDataSize,
LPVOID pOutData,
DWORD cbOutDataSize,
LPDWORD pcbActualData)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::Escape");
// Write command to device if needed.
return STIERR_UNSUPPORTED;
}
/**************************************************************************\
* TestUsdDevice::GetLastError
*
* Get the last error from the device.
*
* Arguments:
*
* pdwLastDeviceError - Pointer to last error data.
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::GetLastError(LPDWORD pdwLastDeviceError)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::GetLastError");
if (IsBadWritePtr(pdwLastDeviceError, sizeof(DWORD))) {
return STIERR_INVALID_PARAM;
}
*pdwLastDeviceError = m_dwLastOperationError;
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::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 TestUsdDevice::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::GetLastErrorInfo");
if (IsBadWritePtr(pLastErrorInfo, sizeof(STI_ERROR_INFO))) {
return STIERR_INVALID_PARAM;
}
pLastErrorInfo->dwGenericError = m_dwLastOperationError;
pLastErrorInfo->szExtendedErrorText[0] = '\0';
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::LockDevice
*
* Lock access to the device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::LockDevice(void)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::LockDevice");
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::UnLockDevice
*
* Unlock access to the device.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::UnLockDevice(void)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::UnLockDevice");
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::RawReadData
*
* Read raw data from the device.
*
* Arguments:
*
* lpBuffer -
* lpdwNumberOfBytes -
* lpOverlapped -
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::RawReadData(
LPVOID lpBuffer,
LPDWORD lpdwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::RawReadData");
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::RawWriteData
*
* Write raw data to the device.
*
* Arguments:
*
* lpBuffer -
* dwNumberOfBytes -
* lpOverlapped -
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::RawWriteData(
LPVOID lpBuffer,
DWORD dwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::RawWriteData");
return STI_OK;
}
/**************************************************************************\
* TestUsdDevice::RawReadCommand
*
*
*
* Arguments:
*
* lpBuffer -
* lpdwNumberOfBytes -
* lpOverlapped -
*
* Return Value:
*
* Status
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::RawReadCommand(
LPVOID lpBuffer,
LPDWORD lpdwNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::RawReadCommand");
return STIERR_UNSUPPORTED;
}
/**************************************************************************\
* TestUsdDevice::RawWriteCommand
*
*
*
* Arguments:
*
* lpBuffer -
* nNumberOfBytes -
* lpOverlapped -
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::RawWriteCommand(
LPVOID lpBuffer,
DWORD nNumberOfBytes,
LPOVERLAPPED lpOverlapped)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::RawWriteCommand");
return STIERR_UNSUPPORTED;
}
/**************************************************************************\
* TestUsdDevice::Initialize
*
* Initialize the device object.
*
* Arguments:
*
* pIStiDevControlNone -
* dwStiVersion -
* hParametersKey -
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
STDMETHODIMP TestUsdDevice::Initialize(
PSTIDEVICECONTROL pIStiDevControl,
DWORD dwStiVersion,
HKEY hParametersKey)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::Initialize");
HRESULT hr = STI_OK;
UINT uiNameLen = 0;
if (!pIStiDevControl) {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::Initialize, invalid device control interface"));
return STIERR_INVALID_PARAM;
}
// Cache the device control interface.
m_pIStiDevControl = pIStiDevControl;
m_pIStiDevControl->AddRef();
// Build the path name of the data source file.
DWORD dwRet = GetTempPath(MAX_PATH, m_szSrcDataName);
if (dwRet != 0) {
_tcscat(m_szSrcDataName, DATA_8BIT_SRC_NAME);
}
else {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::Initialize, unable to get device name"));
return STIERR_NOT_INITIALIZED;
}
// Make sure we can open the data source file.
HANDLE hTestBmp = CreateFile(m_szSrcDataName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM,
NULL);
m_dwLastOperationError = ::GetLastError();
if (hTestBmp == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(m_dwLastOperationError);
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::Initialize, unable to open data source file:"));
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,(" %ls", m_szSrcDataName));
WIAS_LHRESULT(g_pIWiaLog, hr);
}
else {
WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,(" Source data: %ls", m_szSrcDataName));
CloseHandle(hTestBmp);
}
return hr;
}
/**************************************************************************\
* TestUsdDevice::RunNotifications
*
* Monitor changes to the source data file parent directory.
*
* Arguments:
*
* None
*
* Return Value:
*
* Status.
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
VOID TestUsdDevice::RunNotifications(void)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::RunNotifications");
HANDLE hNotifyFileSysChange;
DWORD dwErr;
TCHAR szDirPath[MAX_PATH];
TCHAR *pszLastSlash;
WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("TestUsdDevice::RunNotifications"));
// Find name of the parent directory for the data source file and
// set up waiting on any changes in it.
_tcscpy(szDirPath, m_szSrcDataName);
pszLastSlash = _tcschr(szDirPath,TEXT('\\'));
if (pszLastSlash) {
*pszLastSlash = '\0';
}
hNotifyFileSysChange = FindFirstChangeNotification(szDirPath,
FALSE,
FILE_NOTIFY_CHANGE_SIZE |
FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME);
if (hNotifyFileSysChange == INVALID_HANDLE_VALUE) {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::RunNotifications, FindFirstChangeNotification failed: 0x%08X", ::GetLastError()));
return;
}
// Set initial values for time and size
IsChangeDetected(NULL);
//
HANDLE hEvents[2] = {m_hShutdownEvent, hNotifyFileSysChange};
BOOL fLooping = TRUE;
// Wait for file system change or shutdown event.
while (fLooping) {
dwErr = ::WaitForMultipleObjects(2,
hEvents,
FALSE,
INFINITE);
switch(dwErr) {
case WAIT_OBJECT_0+1:
// Change detected - signal
if (m_hSignalEvent !=INVALID_HANDLE_VALUE) {
// Which change ?
if (IsChangeDetected(&m_guidLastEvent)) {
WIAS_LTRACE(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL4,("Data source file change detected"));
::SetEvent(m_hSignalEvent);
}
}
// Go back to waiting for next file system event
FindNextChangeNotification(hNotifyFileSysChange);
break;
case WAIT_OBJECT_0:
// Fall through
default:
fLooping = FALSE;
}
}
FindCloseChangeNotification(hNotifyFileSysChange);
}
/**************************************************************************\
* TestUsdDevice::IsChangeDetected
*
* Detects changes to the source data file.
*
* Arguments:
*
* pguidEvent - Pointer to event ID.
*
* Return Value:
*
* True if change detected/
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
BOOL TestUsdDevice::IsChangeDetected(GUID *pguidEvent)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"TestUsdDevice::IsChangeDetected");
BOOL bRet = FALSE;
LARGE_INTEGER liNewHugeSize;
FILETIME ftLastWriteTime;
DWORD dwError = NOERROR;
WIN32_FIND_DATA sNewFileAttributes;
HANDLE hFind = INVALID_HANDLE_VALUE;
// Get the source data file attributes.
ZeroMemory(&sNewFileAttributes, sizeof(sNewFileAttributes));
hFind = FindFirstFile( m_szSrcDataName, &sNewFileAttributes );
if (hFind != INVALID_HANDLE_VALUE)
{
ftLastWriteTime = sNewFileAttributes.ftLastWriteTime;
liNewHugeSize.LowPart = sNewFileAttributes.nFileSizeLow;
liNewHugeSize.HighPart = sNewFileAttributes.nFileSizeHigh;
FindClose( hFind );
}
else {
dwError = ::GetLastError();
}
if (NOERROR == dwError) {
// First check file size.
if (m_dwLastHugeSize.QuadPart != liNewHugeSize.QuadPart) {
if (pguidEvent) {
*pguidEvent = guidEventSizeChanged;
}
bRet = TRUE;
}
else {
// Now check file date/time.
if (CompareFileTime(&m_ftLastWriteTime,&ftLastWriteTime) == -1) {
if (pguidEvent) {
*pguidEvent = guidEventTimeChanged;
}
bRet = TRUE;
}
}
m_ftLastWriteTime = ftLastWriteTime;
m_dwLastHugeSize = liNewHugeSize;
}
else {
WIAS_LERROR(g_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TestUsdDevice::IsChangeDetected, Unable to get file attributes: 0x%08X", ::GetLastError()));
}
return bRet;
}
/**************************************************************************\
* FileChangeThread
*
* Calls RunNotifications to detect changing source data file.
*
* Arguments:
*
* lpParameter - Pointer to device object.
*
* Return Value:
*
* None
*
* History:
*
* 9/11/1998 Original Version
*
\**************************************************************************/
VOID FileChangeThread(LPVOID lpParameter)
{
CWiaLogProc WIAS_LOGPROC(g_pIWiaLog,
WIALOG_NO_RESOURCE_ID,
WIALOG_LEVEL3,
"::FileChangeThread");
TestUsdDevice *pThisDevice = (TestUsdDevice *)lpParameter;
pThisDevice->RunNotifications();
}