Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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_