/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 2000 * * TITLE: handler.cpp * * VERSION: 1.0 * * AUTHOR: ByronC * * DATE: 15 Nov, 2000 * * DESCRIPTION: * Declarations and definitions for the WIA messsage handler class. * This class gets called from the Service control function on PnP and Power * event notifications, and informas the device manager to take the appropriate * action. * *******************************************************************************/ #include "precomp.h" #include "stiexe.h" HRESULT CMsgHandler::HandlePnPEvent( DWORD dwEventType, PVOID pEventData) { HRESULT hr = S_OK; PDEV_BROADCAST_HDR pDevHdr = (PDEV_BROADCAST_HDR)pEventData; ACTIVE_DEVICE *pActiveDevice = NULL; DEV_BROADCAST_HEADER *psDevBroadcast = NULL; DEVICE_BROADCAST_INFO *pdbiDevice = NULL; BOOL bFound = FALSE; USES_CONVERSION; DBG_TRC(("CMsgHandler::HandlePnPEvent, dwEventType = 0x%08X", dwEventType)); DBG_WRN(("==> CMsgHandler::HandlePnPEvent")); // // Trace that we are here. For all messages, not intended for StillImage devices , we should refresh // device list if we are running on WIndows NT and registered for device interfaces other than StillImage // PDEV_BROADCAST_DEVNODE pDevNode = (PDEV_BROADCAST_DEVNODE)pDevHdr; PDEV_BROADCAST_DEVICEINTERFACE pDevInterface = (PDEV_BROADCAST_DEVICEINTERFACE)pDevHdr; switch (dwEventType) { case DBT_DEVICEREMOVECOMPLETE: case DBT_DEVICEQUERYREMOVE: case DBT_DEVICEREMOVEPENDING: DBG_TRC(("CMsgHandler::HandlePnPEvent, " "DBT_DEVICEQUERYREMOVE | DBT_DEVICEREMOVEPENDING | DBT_DEVICEREMOVECOMPLETE, " "dwEventType = %lu", dwEventType)); if (IsStillImagePnPMessage(pDevHdr)) { // // Get device name and store along with the broadacast structure // pdbiDevice = new DEVICE_BROADCAST_INFO; if (!pdbiDevice) { DBG_WRN(("CMsgHandler::HandlePnPEvent, out of memory")); return E_OUTOFMEMORY; } // // Fill in information we have // pdbiDevice->m_uiDeviceChangeMessage = dwEventType; pdbiDevice->m_strBroadcastedName.CopyString(pDevInterface->dbcc_name) ; pdbiDevice->m_dwDevNode = pDevNode->dbcd_devnode; // // Try to find our internal device name for this device if it exists in // our internal set. // bFound = GetDeviceNameFromDevBroadcast((DEV_BROADCAST_HEADER *)pDevHdr,pdbiDevice); DBG_WRN(("==> GetDeviceNameFromDevBroadcast returned DeviceID (%ws)", (WCHAR*)(LPCWSTR)pdbiDevice->m_strDeviceName)); if (bFound) { // // Mark that this device has been removed and throw disconnect event. // hr = g_pDevMan->ProcessDeviceRemoval((WCHAR*)(LPCWSTR)pdbiDevice->m_strDeviceName); } else { DBG_TRC(("CMsgHandler::HandlePnPEvent, - failed to get device name from broadcast")); } } else { // // Not exactly one of ours, but we are registered for it, so re-enumerate // g_pDevMan->ReEnumerateDevices(DEV_MAN_GEN_EVENTS); } break; case DBT_DEVICEARRIVAL: DBG_TRC(("CMsgHandler::HandlePnPEvent - DBT_DEVICEARRIVAL")); // // Device has arrived (not installed). We simply find out which of // our devices has changed state. // hr = g_pDevMan->ProcessDeviceArrival(); if (FAILED(hr)) { DBG_WRN(("::CMsgHandler::HandlePnPEvent, unable to enumerate devices")); } break; default: DBG_TRC(("::CMsgHandler::HandlePnPEvent, Default case")); break; } // // Cleanup // if (pdbiDevice) { delete pdbiDevice; } return hr; } DWORD CMsgHandler::HandlePowerEvent( DWORD dwEventType, PVOID pEventData) { DWORD dwRet = NO_ERROR; UINT uiTraceMessage = 0; #ifdef DEBUG static LPCTSTR pszPwrEventNames[] = { TEXT("PBT_APMQUERYSUSPEND"), // 0x0000 TEXT("PBT_APMQUERYSTANDBY"), // 0x0001 TEXT("PBT_APMQUERYSUSPENDFAILED"), // 0x0002 TEXT("PBT_APMQUERYSTANDBYFAILED"), // 0x0003 TEXT("PBT_APMSUSPEND"), // 0x0004 TEXT("PBT_APMSTANDBY"), // 0x0005 TEXT("PBT_APMRESUMECRITICAL"), // 0x0006 TEXT("PBT_APMRESUMESUSPEND"), // 0x0007 TEXT("PBT_APMRESUMESTANDBY"), // 0x0008 // TEXT(" PBTF_APMRESUMEFROMFAILURE"), // 0x00000001 TEXT("PBT_APMBATTERYLOW"), // 0x0009 TEXT("PBT_APMPOWERSTATUSCHANGE"), // 0x000A TEXT("PBT_APMOEMEVENT"), // 0x000B TEXT("PBT_UNKNOWN"), // 0x000C TEXT("PBT_UNKNOWN"), // 0x000D TEXT("PBT_UNKNOWN"), // 0x000E TEXT("PBT_UNKNOWN"), // 0x000F TEXT("PBT_UNKNOWN"), // 0x0010 TEXT("PBT_UNKNOWN"), // 0x0011 TEXT("PBT_APMRESUMEAUTOMATIC"), // 0x0012 }; UINT uiMsgIndex; uiMsgIndex = (dwEventType < (sizeof(pszPwrEventNames) / sizeof(TCHAR *) )) ? (UINT) dwEventType : 0x0010; DBG_TRC(("Still image APM Broadcast Message:%S Code:%x ", pszPwrEventNames[uiMsgIndex],dwEventType)); #endif switch(dwEventType) { case PBT_APMQUERYSUSPEND: // // Request for permission to suspend // if(g_NumberOfActiveTransfers > 0) { // // Veto suspend while any transfers are in progress // dwRet = BROADCAST_QUERY_DENY; } else { // // Notify drivers that we're about to enter a power suspend state // g_pDevMan->NotifyRunningDriversOfEvent(&WIA_EVENT_POWER_SUSPEND); SchedulerSetPauseState(TRUE); } break; case PBT_APMQUERYSUSPENDFAILED: // // Suspension request denied - unpause the scheduler // SchedulerSetPauseState(FALSE); // // Notify drivers that we can resume // g_pDevMan->NotifyRunningDriversOfEvent(&WIA_EVENT_POWER_RESUME); break; case PBT_APMSUSPEND: // // Set the service state to paused // StiServicePause(); uiTraceMessage = MSG_TRACE_PWR_SUSPEND; break; case PBT_APMRESUMECRITICAL: case PBT_APMRESUMEAUTOMATIC: // Operation resuming after critical suspension // Fall through case PBT_APMRESUMESUSPEND: // // Operation resuming after suspension // Restart all services which were active at the moment of suspend // // // ReEnumerate devices. NOTE: we should generate notification only events // g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_GEN_EVENTS); StiServiceResume(); // // Notify drivers that we can resume // g_pDevMan->NotifyRunningDriversOfEvent(&WIA_EVENT_POWER_RESUME); uiTraceMessage = MSG_TRACE_PWR_RESUME; g_fFirstDevNodeChangeMsg = TRUE; break; default: // // This is a message we either don't know about, or have nothing to do. // In either case, we must return NO_ERROR, else the PnP Manager // will assume we're veto'ing the power request. // dwRet = NO_ERROR; } return dwRet; } HRESULT CMsgHandler::HandleCustomEvent( DWORD dwEventType) { HRESULT hr = S_OK; switch (dwEventType) { case STI_SERVICE_CONTROL_EVENT_REREAD : // // For each AVTICE_DEVICE we have, re-read the device settings // hr = g_pDevMan->ForEachDeviceInList(DEV_MAN_OP_DEV_REREAD, 0); if (FAILED(hr)) { DBG_WRN(("::CMsgHandler::HandleCustomEvent, unable to re-read device settings")); } break; default: // // Default case is to refresh our device list // hr = g_pDevMan->ReEnumerateDevices(DEV_MAN_FULL_REFRESH | DEV_MAN_GEN_EVENTS); if (FAILED(hr)) { DBG_WRN(("::CMsgHandler::HandleCustomEvent, unable to enumerate devices")); } } return hr; } HRESULT CMsgHandler::Initialize() { // // Nothing to do for now // return S_OK; }