Example #1
0
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;
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
0
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;
}