Beispiel #1
0
VOID
CNdasDevice::SetGrantedAccess(ACCESS_MASK access)
{
	ximeta::CAutoLock autolock(this);

	// only GENERIC_READ and GENERIC_WRITE are acceptable
	m_grantedAccess = (access & (GENERIC_READ | GENERIC_WRITE));

	const DWORD cbData = sizeof(m_grantedAccess) + sizeof(m_deviceId);
	BYTE lpbData[cbData] = {0};

	::CopyMemory(lpbData, &m_grantedAccess, sizeof(m_grantedAccess));
	::CopyMemory(lpbData + sizeof(m_grantedAccess), &m_deviceId, sizeof(m_deviceId));

	BOOL fSuccess = _NdasSystemCfg.SetSecureValueEx(
		m_szCfgContainer, 
		TEXT("GrantedAccess"), 
		lpbData,
		cbData);

	if (!fSuccess) 
	{
		DBGPRT_WARN_EX(_FT("Writing device access to the registry failed at %s.\n"), 
			m_szCfgContainer);
	}

	(VOID) pGetNdasEventPublisher()->DevicePropertyChanged(m_dwSlotNo);
}
Beispiel #2
0
VOID
CNdasDevice::SetName(LPCTSTR szName)
{
	ximeta::CAutoLock autolock(this);

	HRESULT hr = ::StringCchCopy(
		m_szDeviceName, 
		MAX_NDAS_DEVICE_NAME_LEN, 
		szName);

	_ASSERTE(SUCCEEDED(hr));

	BOOL fSuccess = _NdasSystemCfg.SetValueEx(
		m_szCfgContainer, 
		TEXT("DeviceName"), 
		szName);

	if (!fSuccess) {
		DBGPRT_WARN_EX(
			_FT("Writing device name entry to the registry failed at %s.\n"), 
			m_szCfgContainer);
	}

	CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();
	(VOID) pEventPublisher->DevicePropertyChanged(m_dwSlotNo);
}
Beispiel #3
0
VOID
CNdasDevice::ChangeStatus(NDAS_DEVICE_STATUS newStatus)
{
	ximeta::CAutoLock autolock(this);

	if (m_status == newStatus) {
		return;
	}

	NDAS_DEVICE_STATUS oldStatus = m_status;

	//
	// clear failure count for every status change
	//
	m_dwCommFailureCount = 0;

	switch (newStatus) {
	case NDAS_DEVICE_STATUS_DISABLED:
		{
			pGetNdasDeviceHeartbeatListner()->Detach(this);
			pGetNdasEventMonitor()->Detach(this);
			DestroyAllUnitDevices();
		}
		break;
	case NDAS_DEVICE_STATUS_CONNECTED:
		{
			pGetNdasEventMonitor()->Attach(this);
		}
		break;
	case NDAS_DEVICE_STATUS_DISCONNECTED:
		{
			//
			// Detaching from the Monitor will be done at OnStatusCheck
			// by returning TRUE to detach this device from the monitor
			//
			pGetNdasDeviceHeartbeatListner()->Attach(this);
			DestroyAllUnitDevices();
		}
		break;
	default:
		_ASSERTE(FALSE);
	}

	DBGPRT_INFO(_FT("%s status changed %s to %s\n"),
		ToString(),
		NdasDeviceStatusString(m_status),
		NdasDeviceStatusString(newStatus));

	m_status = newStatus;

	(VOID) pGetNdasEventPublisher()->
		DeviceStatusChanged(m_dwSlotNo, oldStatus, newStatus);

	return;
}
void
CNdasEventMonitor::OnLogicalDeviceAlarmedByPnP(
	__in INdasLogicalUnit* pNdasLogicalUnit, 
	__in ULONG NewAdapterStatus)
{
	NDAS_LOCATION ndasLocation;
	COMVERIFY(pNdasLogicalUnit->get_Id(&ndasLocation));

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Alarm Event, ndasLocation=%08X, logicalUnit=%p\n", 
		ndasLocation, pNdasLogicalUnit);

	if (0 == ndasLocation) 
	{
		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
			"Invalid SCSI Location\n");
		XTLASSERT(FALSE);
		return;
	}

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Logical device alarmed by PnP, ndasLocation=%08X, adapterStatus=%08X.\n", 
		ndasLocation, NewAdapterStatus);

	// Determine whether an alarm will be issued.
	// Only viable alarm will be published
	ULONG currentAdapterStatus;
	COMVERIFY(pNdasLogicalUnit->get_AdapterStatus(&currentAdapterStatus));

	if (pIsViableAlarmStatus(currentAdapterStatus, NewAdapterStatus))
	{
		CNdasEventPublisher& epub = pGetNdasEventPublisher();

		if (ADAPTERINFO_ISSTATUS(NewAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) &&
			ADAPTERINFO_ISSTATUSFLAG(NewAdapterStatus, NDAS_DEVICE_ALARM_STATUSFLAG_ABNORMAL_TERMINAT))
		{
			//
			// Notify abnormal removal of the LU device.
			//
			OnLogicalDeviceDisconnected(pNdasLogicalUnit);
		}
		else
		{
			NDAS_LOGICALDEVICE_ID logicalUnitId;
			COMVERIFY(pNdasLogicalUnit->get_Id(&logicalUnitId));
			(void) epub.LogicalDeviceAlarmed(
				logicalUnitId, 
				pGetSignificantAlarm(currentAdapterStatus, NewAdapterStatus));
		}
	}

	COMVERIFY(pNdasLogicalUnit->put_AdapterStatus(NewAdapterStatus));
}
Beispiel #5
0
VOID 
CNdasLogicalDevice::SetStatus(NDAS_LOGICALDEVICE_STATUS newStatus)
{
	ximeta::CAutoLock autolock(this);

	//
	// Ignore duplicate status change
	//
	if (m_status == newStatus) {
		return;
	}

	NDAS_LOGICALDEVICE_STATUS oldStatus = m_status;

	BOOL fValid = pCheckStatusValidity(m_status, newStatus);
	_ASSERTE(fValid);

	m_status = newStatus;

	// Update Unit Device Status
	for (DWORD i = 0; i < GetUnitDeviceCount(); ++i) {

		CRefObjPtr<CNdasUnitDevice> pUnitDevice = GetUnitDevice(i);

		if (NULL == pUnitDevice.p) {
			DBGPRT_ERR(_FT("Unit Device %s is not found.\n"),
				CNdasUnitDeviceId(GetUnitDeviceID(i)).ToString());
			continue;
		}

		//
		// TODO: Create a status updater with observer
		//

		switch (m_status) {
		case NDAS_LOGICALDEVICE_STATUS_MOUNTED:
		case NDAS_LOGICALDEVICE_STATUS_MOUNT_PENDING:
		case NDAS_LOGICALDEVICE_STATUS_UNMOUNT_PENDING:
			pUnitDevice->SetStatus(NDAS_UNITDEVICE_STATUS_MOUNTED);
			break;
		default:
			// otherwise
			pUnitDevice->SetStatus(NDAS_UNITDEVICE_STATUS_NOT_MOUNTED);
		}

	}
	
	// publish a status change event
	(VOID) pGetNdasEventPublisher()->
		LogicalDeviceStatusChanged(m_logicalDeviceId, oldStatus, newStatus);

}
Beispiel #6
0
VOID
CNdasDevice::SetName(LPCTSTR szName)
{
	ximeta::CAutoLock autolock(this);

	HRESULT hr = ::StringCchCopy(
		m_szDeviceName, 
		MAX_NDAS_DEVICE_NAME_LEN, 
		szName);

	_ASSERTE(SUCCEEDED(hr));

	(VOID) SetConfigValue(_T("DeviceName"), szName);
	(VOID) pGetNdasEventPublisher()->DevicePropertyChanged(m_dwSlotNo);
}
Beispiel #7
0
VOID
CNdasDevice::SetGrantedAccess(ACCESS_MASK access)
{
	ximeta::CAutoLock autolock(this);

	// only GENERIC_READ and GENERIC_WRITE are acceptable
	m_grantedAccess = (access & (GENERIC_READ | GENERIC_WRITE));

	const DWORD cbData = sizeof(m_grantedAccess) + sizeof(m_deviceId);
	BYTE lpbData[cbData] = {0};

	::CopyMemory(lpbData, &m_grantedAccess, sizeof(m_grantedAccess));
	::CopyMemory(lpbData + sizeof(m_grantedAccess), &m_deviceId, sizeof(m_deviceId));

	(VOID) SetConfigValueSecure(_T("GrantedAccess"), lpbData, cbData);
	(VOID) pGetNdasEventPublisher()->DevicePropertyChanged(m_dwSlotNo);
}
void 
CNdasEventMonitor::OnLogicalDeviceDisconnected(
	INdasLogicalUnit* pNdasLogicalUnit)
{
	NDAS_LOCATION location;
	COMVERIFY(pNdasLogicalUnit->get_Id(&location));

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
		"Disconnect Event, ndasLocation=%d, logicalUnit=%p\n", 
		location, pNdasLogicalUnit);

	NDAS_LOGICALDEVICE_ID logicalDeviceId;
	COMVERIFY(pNdasLogicalUnit->get_Id(&logicalDeviceId));

	CNdasEventPublisher& epub = pGetNdasEventPublisher();
	(void) epub.LogicalDeviceDisconnected(logicalDeviceId);

	CComQIPtr<INdasLogicalUnitPnpSink> pNdasLogicalUnitPnpSink(pNdasLogicalUnit);
	pNdasLogicalUnitPnpSink->OnDisconnected();
}
Beispiel #9
0
BOOL CNdasEventMonitor::OnLogicalDeviceDisconnected(DWORD nWaitIndex)
{
	ximeta::CAutoLock autolock(this);

	PCNdasLogicalDevice pLogDevice = NULL;

	if (nWaitIndex < m_vLogDevices.size()) {
		pLogDevice = m_vLogDevices[nWaitIndex];
	} else {
		_ASSERTE(FALSE);
		return TRUE;
	}

	if (NULL == pLogDevice) {
		_ASSERTE(FALSE);
		return TRUE;
	}

	CNdasScsiLocation location = pLogDevice->GetNdasScsiLocation();

	DPInfo(_FT("Disconnect Event from %s: %s\n"),
		location.ToString(),
		pLogDevice->ToString());

	//
	// reset the event to prevent consecutive same event pulse
	//
	BOOL fSuccess = ::ResetEvent(pLogDevice->GetDisconnectEvent());
	_ASSERTE(fSuccess);

	CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();

	NDAS_LOGICALDEVICE_ID logicalDeviceId = pLogDevice->GetLogicalDeviceId();

	(VOID) pEventPublisher->LogicalDeviceDisconnected(logicalDeviceId);

	pLogDevice->OnDisconnected();

	return TRUE;
}
void
CNdasEventMonitor::OnLogicalDeviceAlarmed(INdasLogicalUnit* pNdasLogicalUnit)
{
	NDAS_LOCATION ndasLocation;
	COMVERIFY(pNdasLogicalUnit->get_Id(&ndasLocation));

	NDAS_LOGICALUNIT_ADDRESS ndasLogicalUnitAddress;
	COMVERIFY(pNdasLogicalUnit->get_LogicalUnitAddress(&ndasLogicalUnitAddress));

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Alarm Event, ndasLocation=%d, logicalUnit=%p\n", 
		ndasLocation, pNdasLogicalUnit);

	if (0 == ndasLocation) 
	{
		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
			"Invalid SCSI Location\n");
		XTLASSERT(FALSE);
		return;
	}

	ULONG newAdapterStatus;

	while(TRUE)
	{
		BOOL success = ::NdasBusCtlQueryEvent(
			ndasLocation,
			&newAdapterStatus);

		if (!success) 
		{
			if (::GetLastError() == ERROR_NO_MORE_ITEMS) 
			{
				XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
					"No more events, ignored, ndasLocation=%d\n", 
					ndasLocation);
			} 
			else 
			{
				XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
					"Query status failed on alarm, ignored, ndasLocation=%d\n", 
					ndasLocation);
			}
			return;
		}

		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
			"Logical device alarmed, ndasLocation=%d, adapterStatus=%08X.\n", 
			ndasLocation, newAdapterStatus);

		// Determine whether an alarm will be issued.
		// Only viable alarm will be published
		ULONG currentAdapterStatus;
		COMVERIFY(pNdasLogicalUnit->get_AdapterStatus(&currentAdapterStatus));

		if (pIsViableAlarmStatus(currentAdapterStatus, newAdapterStatus))
		{
			CNdasEventPublisher& epub = pGetNdasEventPublisher();
			NDAS_LOGICALDEVICE_ID logicalUnitId;
			COMVERIFY(pNdasLogicalUnit->get_Id(&logicalUnitId));
			(void) epub.LogicalDeviceAlarmed(
				logicalUnitId, 
				pGetSignificantAlarm(currentAdapterStatus, newAdapterStatus));
		}

		COMVERIFY(pNdasLogicalUnit->put_AdapterStatus(newAdapterStatus));

		if (!ADAPTERINFO_ISSTATUSFLAG(
			newAdapterStatus, 
			NDASSCSI_ADAPTER_STATUSFLAG_NEXT_EVENT_EXIST)) 
		{
			break;
		}
	}
}
Beispiel #11
0
//
// Remove the unit device ID from the list
//
BOOL
CNdasLogicalDevice::RemoveUnitDevice(CNdasUnitDevice& unitDevice)
{
	ximeta::CAutoLock autolock(this);
	DWORD ldSequence = unitDevice.GetLDSequence();

	_ASSERTE(ldSequence < m_logicalDeviceGroup.nUnitDevices);
	if (ldSequence >= m_logicalDeviceGroup.nUnitDevices) {
		DBGPRT_ERR(_FT("Invalid sequence (%d) of the unit device.\n"), ldSequence);
		return FALSE;
	}

	_ASSERTE(&unitDevice == m_pUnitDevices[ldSequence]);
	if (&unitDevice != m_pUnitDevices[ldSequence]) {
		DBGPRT_ERR(_FT("Unit device in sequence (%d) is not occupied.\n"), ldSequence);
		return FALSE;
	}

	m_pUnitDevices[ldSequence]->Release();
	m_pUnitDevices[ldSequence] = NULL;

	//
	// Workaround for Fault-tolerant Mode
	// -> Even if the logical device is incomplete,
	//    Mounted Logical Device Location should be intact
	//    if it is mounted
	//
	if (NDAS_LOGICALDEVICE_STATUS_MOUNT_PENDING == GetStatus() ||
		NDAS_LOGICALDEVICE_STATUS_MOUNTED == GetStatus() ||
		NDAS_LOGICALDEVICE_STATUS_UNMOUNT_PENDING == GetStatus()) 
	{
		--m_nUnitDeviceInstances;
		return TRUE;
	}

	if (IsComplete()) {
		CNdasLogicalDeviceManager* pLdm = pGetNdasLogicalDeviceManager();
		pLdm->UnregisterNdasScsiLocation(m_NdasScsiLocation);
	}

	--m_nUnitDeviceInstances;

	//
	// Deallocation NDAS SCSI Location when the fist unit device is removed
	//
	if (0 == ldSequence) {
		cpDeallocateNdasScsiLocation();
	}

	//
	// Publish Event
	//
	CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();
	(VOID) pEventPublisher->LogicalDeviceRelationChanged(m_logicalDeviceId);

	//
	// Set Device Error
	//
	SetLastDeviceError(NDAS_LOGICALDEVICE_ERROR_MISSING_MEMBER);

	return TRUE;
}
Beispiel #12
0
//
// Set the unit device ID at a sequence 
// to a unit device member ID list
//
BOOL 
CNdasLogicalDevice::AddUnitDevice(CNdasUnitDevice& unitDevice)
{
	ximeta::CAutoLock autolock(this);
	BOOL fSuccess;

	DWORD ldSequence = unitDevice.GetLDSequence();

	_ASSERTE(ldSequence < m_logicalDeviceGroup.nUnitDevices);
	if (ldSequence >= m_logicalDeviceGroup.nUnitDevices) {
		DBGPRT_ERR(_FT("Invalid sequence (%d) of the unit device.\n"), ldSequence);
		return FALSE;
	}

	_ASSERTE(NULL == m_pUnitDevices[ldSequence]);
	if (NULL != m_pUnitDevices[ldSequence]) {
		DBGPRT_ERR(_FT("Sequence (%d) is already occupied.\n"), ldSequence);
		return FALSE;
	}

	_ASSERTE(NULL == m_pUnitDevices[ldSequence]);
	m_pUnitDevices[ldSequence] = &unitDevice;
	m_pUnitDevices[ldSequence]->AddRef();
	++m_nUnitDeviceInstances;

	_ASSERTE(
		m_nUnitDeviceInstances >= 0 && 
		m_nUnitDeviceInstances <= GetUnitDeviceCount()
		);

	if (m_nUnitDeviceInstances < GetUnitDeviceCount()) {
		SetLastDeviceError(NDAS_LOGICALDEVICE_ERROR_MISSING_MEMBER);
	} else {
		SetLastDeviceError(NDAS_LOGICALDEVICE_ERROR_NONE);
	}

	//
	// Allocate NDAS SCSI Location when the first unit device is
	// available
	//
	if (0 == ldSequence) {
		cpAllocateNdasScsiLocation();
	}

	if (IsComplete()) {
		CNdasLogicalDeviceManager* pLdm = pGetNdasLogicalDeviceManager();
		pLdm->RegisterNdasScsiLocation(m_NdasScsiLocation, *this);
	}

	if (IsComplete()) 
	{
		//
		// Reconciliation Support
		//
		BOOL bAlive, bAdapterError;
		fSuccess = ::LsBusCtlQueryNodeAlive(
			m_NdasScsiLocation.SlotNo, 
			&bAlive, 
			&bAdapterError);

		//
		// Reconciliation
		//
		if (fSuccess && bAlive)
		{
			ReconcileFromNdasBus();
		}
	}
	else if (IsComplete() && m_fMountOnReady) 
	{
		//
		// Boot-time Plug In Support
		//

		if ((m_mountOnReadyAccess & GetAllowingAccess()) == 
			m_mountOnReadyAccess)
		{

			(VOID) PlugIn(m_mountOnReadyAccess);

		} else if ((GENERIC_READ & GetAllowingAccess()) && 
			m_fReducedMountOnReadyAccess) 
		{

			(VOID) PlugIn(GENERIC_READ);

		}
	}

	DBGPRT_INFO(_FT("Added %s to Logical Device %s\n"), unitDevice.ToString(), this->ToString());

	CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();
	(VOID) pEventPublisher->LogicalDeviceRelationChanged(m_logicalDeviceId);

	return TRUE;
}
Beispiel #13
0
STDMETHODIMP
CNdasDeviceRegistrar::Deregister(INdasDevice* pNdasDevice)
{
    NDAS_DEVICE_ID ndasDeviceId;
    HRESULT hr;

    COMVERIFY(hr = pNdasDevice->get_NdasDeviceId(&ndasDeviceId));
    if (FAILED(hr))
    {
        return hr;
    }

    DWORD slotNo;
    COMVERIFY(hr = pNdasDevice->get_SlotNo(&slotNo));
    XTLASSERT(0 != slotNo);

    NDAS_DEVICE_STATUS status;
    COMVERIFY(pNdasDevice->get_Status(&status));
    if (NDAS_DEVICE_STATUS_DISABLED != status)
    {
        return NDASSVC_ERROR_CANNOT_UNREGISTER_ENABLED_DEVICE;
    }

    CAutoLock<CLock> autolock(&m_DataLock);

    XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
              "Unregister device %s\n", CNdasDeviceId(ndasDeviceId).ToStringA());

    bool found = false;
    size_t count = m_NdasDevices.GetCount();
    for (size_t i = 0; i < count; ++i)
    {
        CComPtr<INdasDevice> p = m_NdasDevices.GetAt(i);
        if (p == pNdasDevice)
        {
            m_NdasDevices.RemoveAt(i);
            found = true;
            break;
        }
    }

    if (!found)
    {
        return NDASSVC_ERROR_DEVICE_ENTRY_NOT_FOUND;
    }

    DeviceIdMap::iterator itrId = m_deviceIdMap.find(ndasDeviceId);
    ATLASSERT(m_deviceIdMap.end() != itrId);

    DeviceSlotMap::iterator itrSlot = m_deviceSlotMap.find(slotNo);
    ATLASSERT(m_deviceSlotMap.end() != itrSlot);

    m_deviceIdMap.erase(itrId);
    m_deviceSlotMap.erase(itrSlot);

    m_slotbit[slotNo] = false;

    XTL::CStaticStringBuffer<30> containerName(_T("Devices\\%04d"), slotNo);
    BOOL success = _NdasSystemCfg.DeleteContainer(containerName, TRUE);
    if (!success)
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_WARNING,
                  "Deleting registration entry from the registry failed at %ls, error=0x%X\n",
                  containerName, GetLastError());
    }

    autolock.Release();

    (void) pGetNdasEventPublisher().DeviceEntryChanged();

    return S_OK;
}
Beispiel #14
0
STDMETHODIMP
CNdasDeviceRegistrar::Register(
    __in_opt DWORD SlotNo,
    __in const NDAS_DEVICE_ID& DeviceId,
    __in DWORD RegFlags,
    __in_opt const NDASID_EXT_DATA* NdasIdExtension,
    __in BSTR Name,
    __in ACCESS_MASK GrantedAccess,
    __in_opt const NDAS_OEM_CODE* NdasOemCode,
    __deref_out INdasDevice** ppNdasDevice)
{
    HRESULT hr;

    *ppNdasDevice = 0;

    NDAS_DEVICE_ID ndasDeviceId = DeviceId;

    //
    // this will lock this class from here
    // and releases the lock when the function returns;
    //
    CAutoLock<CLock> autolock(&m_DataLock);

    XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
              "Registering device %s at slot %d\n",
              CNdasDeviceId(DeviceId).ToStringA(), SlotNo);

    if (NULL == NdasIdExtension)
    {
        NdasIdExtension = &NDAS_ID_EXTENSION_DEFAULT;
    }

    //
    // Only DEFAULT and SEAGATE are currently implemented
    //
    if (NDAS_VID_SEAGATE != NdasIdExtension->VID	&&
            NDAS_VID_WINDWOS_RO != NdasIdExtension->VID		&&
            NDAS_VID_DEFAULT != NdasIdExtension->VID)
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Unknown Vendor ID=0x%02X\n",
                  NdasIdExtension->VID);

        hr = NDASSVC_ERROR_UNKNOWN_VENDOR_ID;
        return hr;
    }

    ndasDeviceId.VID = NdasIdExtension->VID;

    // If SlotNo is zero, automatically assign it.
    // check slot number
    if (0 == SlotNo)
    {
        SlotNo = pLookupEmptySlot();
        if (0 == SlotNo)
        {
            return NDASSVC_ERROR_DEVICE_ENTRY_SLOT_FULL;
        }
    }
    else if (SlotNo > MAX_SLOT_NUMBER)
    {
        return NDASSVC_ERROR_INVALID_SLOT_NUMBER;
    }

    // check and see if the slot is occupied
    if (m_slotbit[SlotNo])
    {
        return NDASSVC_ERROR_SLOT_ALREADY_OCCUPIED;
    }

    // find an duplicate address
    {
        CComPtr<INdasDevice> pExistingDevice;
        if (SUCCEEDED(get_NdasDevice(&ndasDeviceId, &pExistingDevice)))
        {
            return NDASSVC_ERROR_DUPLICATE_DEVICE_ENTRY;
        }
    }

    // register
    CComObject<CNdasDevice>* pNdasDeviceInstance;
    hr = CComObject<CNdasDevice>::CreateInstance(&pNdasDeviceInstance);
    if (FAILED(hr))
    {
        return hr;
    }

    hr = pNdasDeviceInstance->Initialize(
             SlotNo, ndasDeviceId, RegFlags, NdasIdExtension);
    if (FAILED(hr))
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Device initialization failed, error=0x%X\n", GetLastError());
        return hr;
    }

    CComPtr<INdasDevice> pNdasDevice(pNdasDeviceInstance);

    COMVERIFY(pNdasDevice->put_Name(Name));
    COMVERIFY(pNdasDevice->put_GrantedAccess(GrantedAccess));
    if (NdasOemCode)
    {
        COMVERIFY(pNdasDevice->put_OemCode(NdasOemCode));
    }

    m_slotbit[SlotNo] = true;

    bool insertResult;

    m_NdasDevices.Add(pNdasDevice);

    XTLVERIFY( m_deviceSlotMap.insert(std::make_pair(SlotNo, pNdasDevice)).second );
    //DeviceSlotMap::value_type(SlotNo, pNdasDevice)).second;

    XTLVERIFY( m_deviceIdMap.insert(std::make_pair(ndasDeviceId, pNdasDevice)).second );
    //DeviceIdMap::value_type(ndasDeviceId, pNdasDevice)).second;

    XTLASSERT(m_deviceSlotMap.size() == m_deviceIdMap.size());

    //
    // When NdasIdExtension is NULL, NDAS_ID_EXTENSION_DEFAULT is assigned already
    //

    if (RegFlags & NDAS_DEVICE_REG_FLAG_VOLATILE)
    {
    }
    else
    {
        BOOL success;
        XTL::CStaticStringBuffer<30> containerName(_T("Devices\\%04d"), SlotNo);

        if (0 != memcmp(&NDAS_ID_EXTENSION_DEFAULT, NdasIdExtension, sizeof(NDASID_EXT_DATA)))
        {
            NDAS_DEVICE_ID_REG_DATA regData = {0};
            regData.DeviceId = ndasDeviceId;
            regData.NdasIdExtension = *NdasIdExtension;

            success = _NdasSystemCfg.SetSecureValueEx(
                          containerName,
                          _T("DeviceID2"),
                          &regData,
                          sizeof(regData));
        }
        else
        {
            success = _NdasSystemCfg.SetSecureValueEx(
                          containerName,
                          _T("DeviceID"),
                          &ndasDeviceId,
                          sizeof(ndasDeviceId));
        }

        if (!success)
        {
            XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_WARNING,
                      "Writing registration entry to the registry failed at %ls, error=0x%X\n",
                      containerName.ToString(), GetLastError());
        }

        success = _NdasSystemCfg.SetSecureValueEx(
                      containerName,
                      _T("RegFlags"),
                      &RegFlags,
                      sizeof(RegFlags));

        if (!success)
        {
            XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_WARNING,
                      "Writing registration entry to the registry failed at %ls, error=0x%X\n",
                      containerName.ToString(), GetLastError());
        }
    }

    BOOL publishEvent = !m_fBootstrapping;

    autolock.Release();

    //
    // During bootstrapping, we do not publish this event
    // Bootstrap process will publish an event later
    //

    if (publishEvent)
    {
        (void) pGetNdasEventPublisher().DeviceEntryChanged();
    }

    *ppNdasDevice = pNdasDevice.Detach();

    return S_OK;
}
Beispiel #15
0
BOOL 
CNdasEventMonitor::OnLogicalDeviceAlarmed(DWORD nWaitIndex)
{
	ximeta::CAutoLock autolock(this);

	PCNdasLogicalDevice pLogDevice = NULL;

	if (nWaitIndex < m_vLogDevices.size()) {
		pLogDevice = m_vLogDevices[nWaitIndex];
	} else {
		_ASSERTE(FALSE);
		return FALSE;
	}

	if (NULL == pLogDevice) {
		_ASSERTE(FALSE);
		return FALSE;
	}

	CNdasScsiLocation ndasScsiLocation = pLogDevice->GetNdasScsiLocation();

	DPInfo(_FT("Alarm Event from %s: %s\n"),
		ndasScsiLocation.ToString(),
		pLogDevice->ToString());

	if (ndasScsiLocation.IsInvalid()) {
		DBGPRT_ERR(_FT("Invalid SCSI Location\n"));
		_ASSERTE(FALSE);
		return FALSE;
	}

	//
	// reset the event to prevent consecutive same event pulse
	//
	// should return TRUE
	BOOL fSuccess = ::ResetEvent(pLogDevice->GetAlarmEvent());
	_ASSERTE(fSuccess);

	ULONG ulAdapterStatus;

	fSuccess = ::LsBusCtlQueryStatus(
		ndasScsiLocation.SlotNo,
		&ulAdapterStatus);

	if (!fSuccess) {
		DPErrorEx(_FT("Unable to get alarm status, Ignored: "));
		return TRUE;
	}

	if(pLogDevice->GetAdapterStatus() != ulAdapterStatus)
	{
		pLogDevice->SetAdapterStatus(ulAdapterStatus);

		CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();

		(VOID) pEventPublisher->LogicalDeviceAlarmed(pLogDevice->GetLogicalDeviceId(), ulAdapterStatus);
	}

	if(ADAPTERINFO_ISSTATUSFLAG(ulAdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT))
		pLogDevice->SetAllUnitDevicesFault();

	return TRUE;
}
Beispiel #16
0
BOOL 
CNdasEventMonitor::OnLogicalDeviceAlarmed(DWORD nWaitIndex)
{
	ximeta::CAutoLock autolock(this);

	CNdasLogicalDevice* pLogDevice = NULL;

	if (nWaitIndex < m_vLogDevices.size()) {
		pLogDevice = m_vLogDevices[nWaitIndex];
	} else {
		_ASSERTE(FALSE);
		return FALSE;
	}

	if (NULL == pLogDevice) {
		_ASSERTE(FALSE);
		return FALSE;
	}

	CNdasScsiLocation ndasScsiLocation = pLogDevice->GetNdasScsiLocation();

	DBGPRT_INFO(_FT("Alarm Event from %s: %s\n"),
		ndasScsiLocation.ToString(),
		pLogDevice->ToString());

	if (ndasScsiLocation.IsInvalid()) {
		DBGPRT_ERR(_FT("Invalid SCSI Location\n"));
		_ASSERTE(FALSE);
		return FALSE;
	}

	//
	// reset the event to prevent consecutive same event pulse
	//
	// should return TRUE
	BOOL fSuccess = ::ResetEvent(pLogDevice->GetAlarmEvent());
	_ASSERTE(fSuccess);

	ULONG ulAdapterStatus;

	fSuccess = ::LsBusCtlQueryStatus(
		ndasScsiLocation.SlotNo,
		&ulAdapterStatus);

	if (!fSuccess) {
		DBGPRT_ERR_EX(_FT("(%s) query status failed on alarm, ignored: "), 
			ndasScsiLocation.ToString());
		return TRUE;
	}

	DBGPRT_INFO(_FT("(%s) alarmed %08X.\n"), 
		ndasScsiLocation.ToString(), ulAdapterStatus);

	// Determine whether an alarm will be issued.
	// Only viable alarm will be published
	if(pIsViableAlarmStatus(pLogDevice->GetAdapterStatus(), ulAdapterStatus))
	{
		CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();
		(VOID) pEventPublisher->LogicalDeviceAlarmed(
			pLogDevice->GetLogicalDeviceId(), pGetSignificatAlarm(pLogDevice->GetAdapterStatus(), ulAdapterStatus));
	}

	pLogDevice->SetAdapterStatus(ulAdapterStatus);

	return TRUE;
}
Beispiel #17
0
PCNdasDevice
CNdasDeviceRegistrar::Register(const NDAS_DEVICE_ID& DeviceId, DWORD dwSlotNo)
{
	//
	// this will lock this class from here
	// and releases the lock when the function returns;
	//
	ximeta::CAutoLock autolock(this);
	
	DPInfo(_FT("Registering device %s at slot %d\n"), 
		LPCTSTR(CNdasDeviceId(DeviceId)), dwSlotNo);

	// check slot number
	if (dwSlotNo < 1 || dwSlotNo > m_dwMaxSlotNo) {
		::SetLastError(NDASHLPSVC_ERROR_INVALID_SLOT_NUMBER);
		return NULL;
	}

	// check and see if the slot is occupied
	if (m_pbSlotOccupied[dwSlotNo]) {
		::SetLastError(NDASHLPSVC_ERROR_SLOT_ALREADY_OCCUPIED);
		return NULL;
	}

	// find an duplicate address
	if (NULL != Find(DeviceId)) {
		::SetLastError(NDASHLPSVC_ERROR_DUPLICATE_DEVICE_ENTRY);
		return NULL;
	}

	// register
	PCNdasDevice pDevice = new CNdasDevice(dwSlotNo, DeviceId);
	if (NULL == pDevice) {
		// memory allocation failed
		// No need to set error here!
		return NULL;
	}
	pDevice->AddRef();

	BOOL fSuccess = pDevice->Initialize();
	if (!fSuccess) {
//		DebugPrintError((ERROR_T("Device initialization failed!")));
		pDevice->Release();
		return NULL;
	}

	m_pbSlotOccupied[dwSlotNo] = TRUE;

	bool insertResult;

	insertResult = 
		m_deviceSlotMap.insert(DeviceSlotMap::value_type(dwSlotNo, pDevice)).second;
	_ASSERTE(insertResult == true);
	insertResult =	
		m_deviceIdMap.insert(DeviceIdMap::value_type(DeviceId, pDevice)).second;
	_ASSERTE(insertResult == true);

	_ASSERTE(m_deviceSlotMap.size() == m_deviceIdMap.size());

	TCHAR szContainer[30];
	HRESULT hr = ::StringCchPrintf(szContainer, 30, TEXT("Devices\\%04d"), dwSlotNo);
	_ASSERT(SUCCEEDED(hr));

	fSuccess = _NdasSystemCfg.SetSecureValueEx(
		szContainer, 
		_T("DeviceId"), 
		&DeviceId, 
		sizeof(DeviceId));

	if (!fSuccess) {
		DPWarningEx(
			_FT("Writing registration entry to the registry failed at %s.\n"), 
			szContainer);
	}

	//
	// During bootstrapping, we do not publish this event
	// Bootstrapper will do this later.
	//
	if (!m_fBootstrapping) {
		CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher();
		(VOID) pEventPublisher->DeviceEntryChanged();
	}

	return pDevice;
}