BOOL CNdasDeviceRegistrar::Unregister(const NDAS_DEVICE_ID& DeviceId) { ximeta::CAutoLock autolock(this); CNdasDeviceId cdevid(DeviceId); DPInfo(_FT("Unregister device %s\n"), (LPCTSTR)cdevid); DeviceIdMap::iterator itrId = m_deviceIdMap.find(DeviceId); if (m_deviceIdMap.end() == itrId) { // TODO: ::SetLastError(NDAS_ERROR_DEVICE_NOT_FOUND); // TODO: Make more specific error code ::SetLastError(NDASHLPSVC_ERROR_DEVICE_ENTRY_NOT_FOUND); } PCNdasDevice pDevice = itrId->second; if (pDevice->GetStatus() != NDAS_DEVICE_STATUS_DISABLED) { // TODO: ::SetLastError(NDAS_ERROR_CANNOT_UNREGISTER_ENABLED_DEVICE); // TODO: Make more specific error code ::SetLastError(NDASHLPSVC_ERROR_CANNOT_UNREGISTER_ENABLED_DEVICE); return FALSE; } DWORD dwSlotNo = pDevice->GetSlotNo(); _ASSERT(0 != dwSlotNo); DeviceSlotMap::iterator itrSlot = m_deviceSlotMap.find(dwSlotNo); m_deviceIdMap.erase(itrId); m_deviceSlotMap.erase(itrSlot); m_pbSlotOccupied[dwSlotNo] = FALSE; pDevice->Release(); TCHAR szContainer[30]; HRESULT hr = ::StringCchPrintf(szContainer, 30, TEXT("Devices\\%04d"), dwSlotNo); _ASSERT(SUCCEEDED(hr)); BOOL fSuccess = _NdasSystemCfg.DeleteContainer(szContainer, TRUE); if (!fSuccess) { DPWarningEx( _FT("Deleting registration entry from the registry failed at %s.\n"), szContainer); } CNdasInstanceManager* pInstMan = CNdasInstanceManager::Instance(); _ASSERTE(NULL != pInstMan); CNdasEventPublisher* pEventPublisher = pInstMan->GetEventPublisher(); _ASSERTE(NULL != pEventPublisher); (void) pEventPublisher->DeviceEntryChanged(); return TRUE; }
LRESULT CALLBACK DebugWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DEVICECHANGE: { // // Ignore if pDeviceEventHandler is not available yet. // CNdasInstanceManager* pInstMan = CNdasInstanceManager::Instance(); _ASSERTE(NULL != pInstMan); CNdasServiceDeviceEventHandler *pDeviceEventHandler = pInstMan->GetDeviceEventHandler(); if (NULL == pDeviceEventHandler) { DPWarning(_FT("NdasServicePnpHandler not yet available.\n")); return TRUE; } return pDeviceEventHandler->OnDeviceEvent(wParam, lParam); } case WM_ENDSESSION: { // // ENDSESSION_LOGOFF does not effect to the service // // If lParam is zero, the system is shutting down. if (0 == lParam) { PCNdasService pService = CNdasService::Instance(); if (NULL != pService) { pService->OnServiceShutdown(); } } } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
DWORD CNdasService::OnServiceStop() { // // We should report the SCM that the service is stopping // Otherwise, the service will terminate the thread. // And we'll get ACCESS VIOLATION ERROR! // DBGPRT_INFO(_FT("Service is stopping...\n")); #if 0 // // Eject all logical device instances // if (NULL != GetTaskHandle()) { CNdasInstanceManager* pInstMan = CNdasInstanceManager::Instance(); if (NULL != pInstMan) { CNdasLogicalDeviceManager* pLdm = pInstMan->GetLogDevMan(); if (NULL != pLdm) { pLdm->Lock(); CNdasLogicalDeviceManager::ConstIterator itr = pLdm->begin(); for (; itr != pLdm->end(); ++itr) { CNdasLogicalDevice* pLogDevice = itr->second; if (NDAS_LOGICALDEVICE_STATUS_MOUNTED == pLogDevice->GetStatus()) { // // If we should call pLogDevice->Eject here, // we must wait here until eject is really complete. // BOOL fSuccess = pLogDevice->Eject(); ReportStatusToSCMgr(SERVICE_STOP_PENDING, 3000); ::Sleep(2000); } } pLdm->Unlock(); } } } #endif ReportStatusToSCMgr(SERVICE_STOP_PENDING, 3000); HANDLE hTask = GetTaskHandle(); this->Stop(FALSE); DWORD dwWaitTimeout = 3000L; // 3 sec ReportStatusToSCMgr(SERVICE_STOP_PENDING, 3000); DWORD dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout); if (WAIT_OBJECT_0 == dwWaitResult) { ReportStatusToSCMgr(SERVICE_STOPPED, 1000, NO_ERROR); return NO_ERROR; } ReportStatusToSCMgr(SERVICE_STOP_PENDING); dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout); if (WAIT_OBJECT_0 == dwWaitResult) { ReportStatusToSCMgr(SERVICE_STOPPED, 1000, NO_ERROR); return NO_ERROR; } ReportStatusToSCMgr(SERVICE_STOP_PENDING); dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout); if (WAIT_OBJECT_0 == dwWaitResult) { ReportStatusToSCMgr(SERVICE_STOPPED, 1000, NO_ERROR); return NO_ERROR; } ReportStatusToSCMgr(SERVICE_STOP_PENDING); dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout); if (dwWaitResult == WAIT_TIMEOUT) { } ReportStatusToSCMgr(SERVICE_STOPPED, 100, 1); return 1; }
DWORD CNdasEventMonitor:: OnTaskStart() { BOOL bTerminateThread(FALSE); // 15 sec = 10,000,000 nanosec // negative value means relative time LARGE_INTEGER liDueTime; liDueTime.QuadPart = - 10 * 1000 * 1000; BOOL fSuccess = ::SetWaitableTimer( m_hHeartbeatMonitorTimer, &liDueTime, HEARTBEAT_MONITOR_INTERVAL, NULL, NULL, FALSE); if (!fSuccess) { DPErrorEx(_FT("Setting waitable timer failed: ")); } do { // // Lock against m_vLogDevice set change // this->Lock(); DWORD dwLogDevices = m_vLogDevices.size(); DWORD dwHandles = 3 + 2 * dwLogDevices; HANDLE* hWaitingHandles = new HANDLE[dwHandles]; hWaitingHandles[0] = m_hTaskTerminateEvent; hWaitingHandles[1] = m_hLogDeviceSetChangeEvent; hWaitingHandles[2] = m_hHeartbeatMonitorTimer; PCNdasLogicalDeviceVector::const_iterator itr = m_vLogDevices.begin(); for (DWORD i = 3; itr != m_vLogDevices.end(); ++itr, ++i) { PCNdasLogicalDevice pLogDevice = *itr; hWaitingHandles[i] = pLogDevice->GetDisconnectEvent(); hWaitingHandles[dwLogDevices + i] = pLogDevice->GetAlarmEvent(); } this->Unlock(); BOOL fSuccess = ::ResetEvent(m_hLogDeviceSetChangeEvent); _ASSERTE(fSuccess); BOOL bResetLogDeviceSet(FALSE); do { DWORD dwWaitResult = ::WaitForMultipleObjects( dwHandles, hWaitingHandles, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwWaitResult) { // // Terminate Thread Event // bTerminateThread = TRUE; } else if (WAIT_OBJECT_0 + 1 == dwWaitResult) { // // LogicalDeviceSetChange Event // bResetLogDeviceSet = TRUE; } else if (WAIT_OBJECT_0 + 2 == dwWaitResult) { // // Heartbeat Monitor Timer Event // ximeta::CAutoLock autolock(this); PCNdasDeviceSet::const_iterator itr = m_hbMonDevices.begin(); m_bIterating = TRUE; for (; itr != m_hbMonDevices.end();) { PCNdasDevice pDevice = *itr; BOOL bDetach = pDevice->OnStatusCheck(); if (bDetach) { DPInfo(_FT("Detaching device %s from the monitor\n"), CNdasDeviceId(pDevice->GetDeviceId()).ToString()); itr = m_hbMonDevices.erase(itr); } else { ++itr; } } m_bIterating = FALSE; } else if (WAIT_OBJECT_0 + 3 <= dwWaitResult && dwWaitResult < WAIT_OBJECT_0 + 3 + dwLogDevices) { // // Disconnect Event // DWORD n = dwWaitResult - (WAIT_OBJECT_0 + 3); PCNdasLogicalDevice pLogDevice = m_vLogDevices[n]; DPInfo(_FT("Disconnect Event from slot %d: %s\n"), pLogDevice->GetSlot(), pLogDevice->ToString()); // // Publish event here // // TODO: Publish event here // CNdasInstanceManager* pInstMan = CNdasInstanceManager::Instance(); _ASSERTE(NULL != pInstMan); CNdasEventPublisher* pEventPublisher = pInstMan->GetEventPublisher(); _ASSERTE(NULL != pEventPublisher); NDAS_LOGICALDEVICE_ID logicalDeviceId = {0}; logicalDeviceId.SlotNo = pLogDevice->GetSlot(); logicalDeviceId.TargetId = 0; logicalDeviceId.LUN = 0; (void) pEventPublisher->LogicalDeviceDisconnected(logicalDeviceId); BOOL fSuccess = ::ResetEvent(pLogDevice->GetDisconnectEvent()); _ASSERTE(fSuccess); // // Eject device // DPInfo(_FT("Ejecting disconnected logical device\n")); fSuccess = pLogDevice->Eject(); if (!fSuccess) { DPErrorEx(_FT("Eject failed: ")); DPError(_FT("Trying to unplug...\n")); fSuccess = pLogDevice->Unplug(); if (!fSuccess) { DPErrorEx(_FT("Unplugging failed: ")); } } } else if (WAIT_OBJECT_0 + 3 + dwLogDevices <= dwWaitResult && dwWaitResult < WAIT_OBJECT_0 + 3 + 2 * dwLogDevices) { // // Alarm Event // DWORD n = dwWaitResult - (WAIT_OBJECT_0 + 3 + dwLogDevices); PCNdasLogicalDevice pLogDevice = m_vLogDevices[n]; ULONG ulStatus; DPInfo(_FT("Alarm Event from slot %d: %s\n"), pLogDevice->GetSlot(), pLogDevice->ToString()); LsBusCtlQueryAlarmStatus(pLogDevice->GetSlot(), &ulStatus); CNdasInstanceManager* pInstMan = CNdasInstanceManager::Instance(); _ASSERTE(NULL != pInstMan); CNdasEventPublisher* pEventPublisher = pInstMan->GetEventPublisher(); _ASSERTE(NULL != pEventPublisher); switch (ulStatus) { case ALARM_STATUS_NORMAL: { DPInfo(_FT("Alarm Normal\n")); NDAS_LOGICALDEVICE_ID logicalDeviceId = {0}; logicalDeviceId.SlotNo = pLogDevice->GetSlot(); logicalDeviceId.TargetId = 0; logicalDeviceId.LUN = 0; (void) pEventPublisher-> LogicalDeviceReconnected(logicalDeviceId); } break; case ALARM_STATUS_START_RECONNECT: { DPInfo(_FT("Alarm Start Reconnect\n")); NDAS_LOGICALDEVICE_ID logicalDeviceId = {0}; logicalDeviceId.SlotNo = pLogDevice->GetSlot(); logicalDeviceId.TargetId = 0; logicalDeviceId.LUN = 0; (void) pEventPublisher-> LogicalDeviceReconnecting(logicalDeviceId); } break; case ALARM_STATUS_FAIL_RECONNECT: // obsolete DPInfo(_FT("Alarm Failed Reconnecting\n")); break; default: DPWarning(_FT("Unknown alarm status: %d\n"), ulStatus); } // // TODO: Publish event here // BOOL fSuccess = ::ResetEvent(pLogDevice->GetAlarmEvent()); _ASSERTE(fSuccess); } else { _ASSERTE(FALSE); DPErrorEx(_FT("Wait failed: ")); } } while (!bResetLogDeviceSet && !bTerminateThread); delete [] hWaitingHandles; } while (!bTerminateThread); fSuccess = ::CancelWaitableTimer(m_hHeartbeatMonitorTimer); if (!fSuccess) { DPErrorEx(_FT("Canceling waitable timer failed: ")); } return 0; }