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.
568 lines
12 KiB
568 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
device.h
|
|
|
|
Abstract:
|
|
|
|
Handling opened device object on the monitor side
|
|
|
|
Author:
|
|
|
|
Vlad Sadovsky (vlads) 10-Jan-1997
|
|
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
26-Jan-1997 VladS created
|
|
|
|
--*/
|
|
|
|
#ifndef _DEVICE_H_
|
|
#define _DEVICE_H_
|
|
|
|
#include <base.h>
|
|
#include <buffer.h>
|
|
|
|
class CWiaDrvItem;
|
|
//
|
|
// If this code is moved into dll, methods will need to be exported in order to instantiate
|
|
// objects of those classes outside module scope. Then we will need to replace line below
|
|
//
|
|
// #define dllexp __declspec( dllexport )
|
|
//
|
|
#undef dllexp
|
|
#define dllexp
|
|
//
|
|
|
|
#define PRIVATE_FOR_NO_SERVICE_UI
|
|
|
|
//
|
|
// Type of syncronization for accessing device object
|
|
//
|
|
#define USE_CRITICAL_SECTION 1
|
|
|
|
/***********************************************************
|
|
* Type Definitions
|
|
************************************************************/
|
|
|
|
#define ADEV_SIGNATURE (DWORD)'ADEV'
|
|
#define ADEV_SIGNATURE_FREE (DWORD)'FDEV'
|
|
|
|
//
|
|
// Values for flags field for device object
|
|
//
|
|
|
|
#define STIMON_AD_FLAG_POLLING 0x000001 // Device requires polling
|
|
#define STIMON_AD_FLAG_OPENED_FOR_DATA 0x000002 // Device is opened for data access
|
|
#define STIMON_AD_FLAG_LAUNCH_PENDING 0x000004 // Auto launch is pending
|
|
#define STIMON_AD_FLAG_REMOVING 0x000008 // Device is being removed
|
|
#define STIMON_AD_FLAG_NOTIFY_ENABLED 0x000010 // Nobody disabled notifications
|
|
#define STIMON_AD_FLAG_NOTIFY_CAPABLE 0x000020 // Device is capable to notify
|
|
#define STIMON_AD_FLAG_NOTIFY_RUNNING 0x000040 // Currently monitor is receiving notificaitons from device
|
|
#define STIMON_AD_FLAG_MARKED_INACTIVE 0x000080 // Currently monitor is receiving notificaitons from device
|
|
#define STIMON_AD_FLAG_DELAYED_INIT 0x000100 // Currently monitor is receiving notificaitons from device
|
|
|
|
|
|
#define STIDEV_POLL_FAILURE_REPORT_COUNT 25 // Skip reporting errors on each polling attempt
|
|
|
|
#define STIDEV_DELAYED_INTIT_TIME 10 // No. of milliseconds to schedule delayed init
|
|
|
|
#define STIDEV_MIN_POLL_TIME 100 // Shortest poll interval allowed
|
|
|
|
//
|
|
// Forward declarations
|
|
//
|
|
class STI_CONN;
|
|
class ACTIVE_DEVICE;
|
|
class FakeStiDevice;
|
|
|
|
//
|
|
// Device Event code structure. A list of these is maintained for each
|
|
// active device. This list is initialized from the registry when the
|
|
// device becomes active (in the ACTIVE_DEVICE constructor).
|
|
// Each even code structure contains an event code that the device
|
|
// can issue. This event code is validated against this list. If valid,
|
|
// the action assoicated with the event is triggered.
|
|
//
|
|
typedef struct _DEVICEEVENT {
|
|
LIST_ENTRY m_ListEntry;
|
|
GUID m_EventGuid;
|
|
StiCString m_EventSubKey;
|
|
StiCString m_EventName;
|
|
StiCString m_EventData;
|
|
BOOL m_fLaunchable;
|
|
} DEVICEEVENT, *PDEVICEEVENT;
|
|
|
|
|
|
//
|
|
// Container to pass parameters to auto launch thread
|
|
//
|
|
typedef struct _AUTO_LAUNCH_PARAM_CONTAINER {
|
|
ACTIVE_DEVICE *pActiveDevice;
|
|
PDEVICEEVENT pLaunchEvent;
|
|
LPCTSTR pAppName;
|
|
} AUTO_LAUNCH_PARAM_CONTAINER,*PAUTO_LAUNCH_PARAM_CONTAINER;
|
|
|
|
|
|
class ACTIVE_DEVICE : public BASE {
|
|
|
|
friend class TAKE_ACTIVE_DEVICE;
|
|
|
|
friend VOID CALLBACK
|
|
DumpActiveDevicesCallback(
|
|
ACTIVE_DEVICE *pActiveDevice,
|
|
VOID *pContext
|
|
);
|
|
|
|
public:
|
|
|
|
// *** IUnknown methods ***
|
|
STDMETHODIMP QueryInterface( REFIID riid, LPVOID * ppvObj);
|
|
STDMETHODIMP_(ULONG) AddRef( void);
|
|
STDMETHODIMP_(ULONG) Release( void);
|
|
|
|
//
|
|
ACTIVE_DEVICE(IN LPCTSTR lpszDeviceName, DEVICE_INFO *pInfo = NULL);
|
|
|
|
~ACTIVE_DEVICE( VOID ) ;
|
|
|
|
inline BOOL
|
|
IsValid(
|
|
VOID
|
|
)
|
|
{
|
|
return (m_fValid) && (m_dwSignature == ADEV_SIGNATURE);
|
|
}
|
|
|
|
inline BOOL
|
|
EnterCrit(VOID)
|
|
{
|
|
return m_dwDeviceCritSec.Lock();
|
|
}
|
|
|
|
inline void
|
|
LeaveCrit(VOID)
|
|
{
|
|
m_dwDeviceCritSec.Unlock();
|
|
}
|
|
|
|
inline DWORD
|
|
SetFlags(
|
|
DWORD dwNewFlags
|
|
)
|
|
{
|
|
DWORD dwTemp = m_dwFlags;
|
|
m_dwFlags = dwNewFlags;
|
|
return dwTemp;
|
|
}
|
|
|
|
inline DWORD
|
|
QueryFlags(
|
|
VOID
|
|
)
|
|
{
|
|
return m_dwFlags;
|
|
}
|
|
|
|
|
|
inline DWORD
|
|
QueryPollingInterval(VOID) // get current polling interval
|
|
{
|
|
return m_dwPollingInterval;
|
|
}
|
|
|
|
inline DWORD
|
|
SetPollingInterval(
|
|
IN DWORD dwNewInterval) // Set new interval for polling
|
|
{
|
|
DWORD dwTemp = m_dwPollingInterval;
|
|
|
|
m_dwPollingInterval = dwNewInterval;
|
|
|
|
return dwTemp;
|
|
}
|
|
|
|
inline BOOL
|
|
IsConnectedTo(
|
|
VOID
|
|
)
|
|
{
|
|
return !IsListEmpty(&m_ConnectionListHead);
|
|
}
|
|
|
|
|
|
BOOL
|
|
NotificationsNeeded(
|
|
VOID
|
|
)
|
|
{
|
|
if (!IsListEmpty(&m_ConnectionListHead)) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// If setup is running - block all events
|
|
//
|
|
if ( IsSetupInProgressMode() ) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// For async. notification devices always assume they need support for notificaitons
|
|
// It is rather hacky , but all USB devices we have now, need to initialize notifications
|
|
// support on startup, otherwise their initialization routines would not complete properly.
|
|
// It is not expensive to monitor async events and do nothing when they arrive
|
|
// For polled devices on the ontrary , it is quite expensive to keep monitoring
|
|
// events ,when they are really not needed
|
|
|
|
if ((QueryFlags() & STIMON_AD_FLAG_NOTIFY_CAPABLE) &&
|
|
!(QueryFlags() & STIMON_AD_FLAG_POLLING) ) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
// If there are no connections, then check whether user does not want notifications or
|
|
// event list is empty
|
|
return ( !m_dwUserDisableNotifications && m_fLaunchableEventListNotEmpty );
|
|
}
|
|
}
|
|
|
|
WCHAR* GetDeviceID()
|
|
{
|
|
return m_DrvWrapper.getDeviceId();
|
|
}
|
|
|
|
HANDLE GetNotificationsSink()
|
|
{
|
|
return m_hDeviceNotificationSink;
|
|
}
|
|
|
|
VOID
|
|
GetDeviceSettings(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Device notifications spport
|
|
//
|
|
BOOL
|
|
BuildEventList(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
DestroyEventList(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
DisableDeviceNotifications(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
EnableDeviceNotifications(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
StopNotifications(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
StartRunningNotifications(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
FlushDeviceNotifications(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
DoPoll(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
DoAsyncEvent(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
ProcessEvent(
|
|
STINOTIFY *psNotify,
|
|
BOOL fForceLaunch=FALSE,
|
|
LPCTSTR pszAppName=NULL
|
|
);
|
|
|
|
BOOL
|
|
AutoLaunch(
|
|
PAUTO_LAUNCH_PARAM_CONTAINER pAutoContainer
|
|
);
|
|
|
|
BOOL
|
|
RetrieveSTILaunchInformation(
|
|
PDEVICEEVENT pev,
|
|
LPCTSTR pAppName,
|
|
STRArray& saAppList,
|
|
STRArray& saCommandLine,
|
|
BOOL fForceSelection=FALSE
|
|
);
|
|
|
|
BOOL
|
|
IsDeviceAvailable(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
RemoveConnection(
|
|
STI_CONN *pConnection
|
|
);
|
|
|
|
BOOL
|
|
AddConnection(
|
|
STI_CONN *pConnection
|
|
);
|
|
|
|
STI_CONN *
|
|
FindMyConnection(
|
|
HANDLE hConnection
|
|
);
|
|
|
|
BOOL
|
|
FillEventFromUSD(
|
|
STINOTIFY *psNotify
|
|
);
|
|
|
|
BOOL
|
|
SetHandleForUSD(
|
|
HANDLE hEvent
|
|
);
|
|
|
|
BOOL
|
|
IsEventOnArrivalNeeded(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Load/Unload STI device
|
|
//
|
|
BOOL
|
|
LoadDriver(
|
|
BOOL bReReadDevInfo = FALSE
|
|
);
|
|
|
|
BOOL
|
|
UnLoadDriver(
|
|
BOOL bForceUnload
|
|
);
|
|
|
|
//
|
|
// PnP support methods
|
|
//
|
|
BOOL
|
|
InitPnPNotifications(
|
|
HWND hwnd
|
|
);
|
|
|
|
BOOL
|
|
StopPnPNotifications(
|
|
VOID
|
|
);
|
|
|
|
BOOL IsRegisteredForDeviceRemoval(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Update WIA cached device information
|
|
//
|
|
|
|
BOOL UpdateDeviceInformation(
|
|
VOID
|
|
);
|
|
|
|
VOID SetDriverItem(
|
|
CWiaDrvItem *pRootDrvItem)
|
|
{
|
|
|
|
//
|
|
// Note: Technically, we should follow proper ref-counting
|
|
// procedure for this this object. However, we should NEVER have
|
|
// the case where this object goes out of scope (or otherwise
|
|
// destroyed) without our knowledge, therefore there is no need.
|
|
//
|
|
m_pRootDrvItem = pRootDrvItem;
|
|
};
|
|
|
|
//
|
|
LIST_ENTRY m_ListEntry;
|
|
LIST_ENTRY m_ConnectionListHead;
|
|
DWORD m_dwSignature;
|
|
|
|
StiCString m_strLaunchCommandLine;
|
|
|
|
LONG m_lDeviceId;
|
|
|
|
PVOID m_pLockInfo;
|
|
DWORD m_dwDelayedOpCookie;
|
|
|
|
FakeStiDevice *m_pFakeStiDevice;
|
|
CDrvWrap m_DrvWrapper;
|
|
CWiaDrvItem *m_pRootDrvItem;
|
|
|
|
private:
|
|
|
|
BOOL m_fValid;
|
|
BOOL m_fLaunchableEventListNotEmpty;
|
|
BOOL m_fRefreshedBusOnFailure;
|
|
|
|
CRIT_SECT m_dwDeviceCritSec;
|
|
|
|
DWORD m_dwFlags;
|
|
DWORD m_dwPollingInterval;
|
|
DWORD m_dwUserDisableNotifications;
|
|
DWORD m_dwSchedulerCookie;
|
|
DWORD m_dwLaunchEventTimeExpire;
|
|
|
|
UINT m_uiSubscribersCount;
|
|
|
|
UINT m_uiPollFailureCount;
|
|
|
|
HANDLE m_hDeviceEvent;
|
|
HANDLE m_hDeviceNotificationSink;
|
|
HANDLE m_hDeviceInterface;
|
|
|
|
STI_DEVICE_STATUS m_DevStatus;
|
|
|
|
LIST_ENTRY m_DeviceEventListHead;
|
|
|
|
PDEVICEEVENT m_pLastLaunchEvent;
|
|
};
|
|
|
|
|
|
//
|
|
// Take device class
|
|
//
|
|
class TAKE_ACTIVE_DEVICE
|
|
{
|
|
private:
|
|
ACTIVE_DEVICE* m_pDev;
|
|
BOOL m_bLocked;
|
|
|
|
public:
|
|
|
|
inline TAKE_ACTIVE_DEVICE(ACTIVE_DEVICE* pdev) : m_pDev(pdev), m_bLocked(FALSE)
|
|
{
|
|
if (m_pDev) {
|
|
m_bLocked = m_pDev->EnterCrit();
|
|
}
|
|
}
|
|
|
|
inline ~TAKE_ACTIVE_DEVICE()
|
|
{
|
|
if (m_bLocked) {
|
|
m_pDev->LeaveCrit();
|
|
}
|
|
}
|
|
};
|
|
|
|
//
|
|
// Linked list for active STI devices, known to monitor
|
|
//
|
|
extern LIST_ENTRY g_pDeviceListHead;
|
|
|
|
//
|
|
//
|
|
// Add/Remove device object from the list
|
|
//
|
|
BOOL
|
|
AddDeviceByName(
|
|
LPCTSTR pszDeviceName,
|
|
BOOL fPnPInitiated = FALSE
|
|
);
|
|
|
|
BOOL
|
|
RemoveDeviceByName(
|
|
LPTSTR pszDeviceName
|
|
);
|
|
|
|
BOOL
|
|
MarkDeviceForRemoval(
|
|
LPTSTR pszDeviceName
|
|
);
|
|
|
|
// Reload device list in response to PnP or ACPI notifications
|
|
//
|
|
|
|
VOID
|
|
RefreshDeviceList(
|
|
WORD wCommand,
|
|
WORD wFlags
|
|
);
|
|
|
|
//
|
|
// Initialize/Terminate linked list
|
|
//
|
|
VOID
|
|
InitializeDeviceList(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TerminateDeviceList(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
DebugDumpDeviceList(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
ResetAllPollIntervals(
|
|
UINT dwNewPollInterval
|
|
);
|
|
|
|
//
|
|
// Enumerators with callbacks
|
|
//
|
|
|
|
typedef
|
|
VOID
|
|
(*PFN_DEVINFO_CALLBACK)(
|
|
PSTI_DEVICE_INFORMATION pDevInfo,
|
|
VOID *pContext
|
|
);
|
|
|
|
typedef
|
|
VOID
|
|
(* PFN_ACTIVEDEVICE_CALLBACK)(
|
|
ACTIVE_DEVICE *pActiveDevice,
|
|
VOID *pContext
|
|
);
|
|
/*
|
|
VOID
|
|
WINAPI
|
|
EnumerateStiDevicesWithCallback(
|
|
PFN_DEVINFO_CALLBACK pfn,
|
|
VOID *pContext
|
|
);
|
|
*/
|
|
|
|
VOID
|
|
WINAPI
|
|
EnumerateActiveDevicesWithCallback(
|
|
PFN_ACTIVEDEVICE_CALLBACK pfn,
|
|
VOID *pContext
|
|
);
|
|
#endif // _DEVICE_H_
|