Пример #1
0
VOID
CNdasEventMonitor::
Attach(const PCNdasDevice pDevice)
{
	ximeta::CAutoLock autolock(this);

	DPInfo(_FT("Attaching device %s to the monitor\n"),
		CNdasDeviceId(pDevice->GetDeviceId()).ToString());

	std::pair<PCNdasDeviceSet::iterator,bool> ins = m_hbMonDevices.insert(pDevice);
}
Пример #2
0
VOID
CNdasEventMonitor::Attach(CNdasDevice* pDevice)
{
	ximeta::CAutoLock autolock(this);

	pDevice->AddRef();

	DBGPRT_INFO(_FT("Attaching device %s to the monitor\n"),
		CNdasDeviceId(pDevice->GetDeviceId()).ToString());

	std::pair<CNdasDeviceSet::iterator,bool> ins = m_hbMonDevices.insert(pDevice);
}
Пример #3
0
LPCTSTR
CNdasDevice::ToString()
{
	ximeta::CAutoLock autolock(this);

	HRESULT hr = ::StringCchPrintf(
		m_lpStrBuf, 
		m_cchStrBuf,
		_T("{%03X}%s"),
		m_dwSlotNo, 
		CNdasDeviceId(m_deviceId).ToString());

	return m_lpStrBuf;
}
Пример #4
0
VOID
CNdasEventMonitor::
Detach(const PCNdasDevice pDevice)
{
	ximeta::CAutoLock autolock(this);

	_ASSERTE(!m_bIterating && 
		"You must not call Detach from OnStatusCheck" &&
		"Return TRUE to detach during OnStatusCheck instead!");

	DPInfo(_FT("Detaching device %s from the monitor\n"),
		CNdasDeviceId(pDevice->GetDeviceId()).ToString());

	m_hbMonDevices.erase(pDevice);
}
Пример #5
0
BOOL 
CNdasDeviceRegistrar::Unregister(const NDAS_DEVICE_ID& DeviceId)
{
	InstanceAutoLock autolock(this);

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

	DeviceIdMap::iterator itrId = m_deviceIdMap.find(DeviceId);
	if (m_deviceIdMap.end() == itrId) 
	{
		::SetLastError(NDASSVC_ERROR_DEVICE_ENTRY_NOT_FOUND);
	}

	CNdasDevicePtr pDevice = itrId->second;
	
	if (pDevice->GetStatus() != NDAS_DEVICE_STATUS_DISABLED) 
	{
		::SetLastError(NDASSVC_ERROR_CANNOT_UNREGISTER_ENABLED_DEVICE);
		return FALSE;
	}

	DWORD SlotNo = pDevice->GetSlotNo();
	XTLASSERT(0 != SlotNo);

	DeviceSlotMap::iterator itrSlot = m_deviceSlotMap.find(SlotNo);

	m_deviceIdMap.erase(itrId);
	m_deviceSlotMap.erase(itrSlot);
	m_slotbit[SlotNo] = false;

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

	(void) m_service.GetEventPublisher().DeviceEntryChanged();

	return TRUE;
}
Пример #6
0
VOID
CNdasEventMonitor::Detach(CNdasDevice* pDevice)
{
	ximeta::CAutoLock autolock(this);

	_ASSERTE(!m_bIterating && 
		"You must not call Detach from OnStatusCheck" &&
		"Return TRUE to detach during OnStatusCheck instead!");

	DPInfo(_FT("Detaching device %s from the monitor\n"),
		CNdasDeviceId(pDevice->GetDeviceId()).ToString());

	PCNdasDeviceSet::size_type nErased = m_hbMonDevices.erase(pDevice);
	_ASSERTE(0 == nErased || 1 == nErased);

	if (nErased == 1) {
		pDevice->Release();
	}
}
Пример #7
0
STDMETHODIMP
CNdasDeviceRegistrar::Bootstrap()
{
    HRESULT hr;

    BOOL success = FALSE;
    BOOL fMigrated = FALSE;

    //
    // Set bootstrapping flag to prevent multiple events
    // for DeviceSetChange Events
    //

    m_fBootstrapping = TRUE;

    TCHAR szSubcontainer[30] = {0};
    for (DWORD i = 0; i < MAX_SLOT_NUMBER; ++i)
    {
        COMVERIFY(StringCchPrintf(
                      szSubcontainer, 30, _T("%s\\%04d"), CFG_CONTAINER, i));

        BOOL fAutoRegistered = FALSE;
        success = _NdasSystemCfg.GetValueEx(
                      szSubcontainer,
                      _T("AutoRegistered"),
                      &fAutoRegistered);

        if (success && fAutoRegistered)
        {
            XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
                      "Deleting %ls\n", szSubcontainer);
            // Auto registered devices are not persistent
            // it is an error to show up here.
            // We just ignore those entries
            success = _NdasSystemCfg.DeleteContainer(szSubcontainer, TRUE);
            if (!success)
            {
                XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
                          "Deleting a RegKey=%ls failed, error=0x%X\n",
                          szSubcontainer, GetLastError());
            }
            continue;
        }

        DWORD cbUsed;

        NDAS_DEVICE_ID_REG_DATA regData = {0};
        const NDASID_EXT_DATA* ndasIdExtension = NULL;

        success = _NdasSystemCfg.GetSecureValueEx(
                      szSubcontainer,
                      _T("DeviceID2"),
                      &regData,
                      sizeof(NDAS_DEVICE_ID_REG_DATA),
                      &cbUsed);

        if (!success)
        {
            //
            // Non-extension data
            //
            success = _NdasSystemCfg.GetSecureValueEx(
                          szSubcontainer,
                          _T("DeviceID"),
                          &regData.DeviceId,
                          sizeof(regData.DeviceId),
                          &cbUsed);

            //
            // ignore read fault - tampered or not exists
            //
            if (!success || cbUsed != sizeof(NDAS_DEVICE_ID))
            {
                continue;
            }
            // For VID's other than 1 (or 0), DeviceID2 should be used instead.
            // In this case, VID is 1.
            // (Assume VID 0 is VID 1 to support registry entry created
            // by older software(~3.11))
            regData.DeviceId.VID = 1;
        }
        else
        {
            if (cbUsed != sizeof(NDAS_DEVICE_ID_REG_DATA))
            {
                //
                // maybe more recent versions, unrecognized, ignore
                //
                continue;
            }
            // DeviceId.VID may not be written correctly by some version of SW.
            regData.DeviceId.VID = regData.NdasIdExtension.VID;
            ndasIdExtension = &regData.NdasIdExtension;
        }

        //
        // RegFlags
        //

        DWORD regFlags;
        success = _NdasSystemCfg.GetSecureValueEx(
                      szSubcontainer,
                      _T("RegFlags"),
                      &regFlags,
                      sizeof(regFlags));

        if (!success)
        {
            regFlags = NDAS_DEVICE_REG_FLAG_NONE;
        }

        //
        // NDAS OEM Code
        //

        const NDAS_OEM_CODE* ndasOemCode = NULL;
        NDAS_OEM_CODE ndasOemCodeBuffer;
        success = _NdasSystemCfg.GetSecureValueEx(
                      szSubcontainer,
                      _T("OEMCode"),
                      &ndasOemCodeBuffer,
                      sizeof(NDAS_OEM_CODE),
                      &cbUsed);

        if (success && cbUsed == sizeof(NDAS_OEM_CODE))
        {
            ndasOemCode = &ndasOemCodeBuffer;
        }

        //
        // Granted Access
        //

        ACCESS_MASK grantedAccess = GENERIC_READ;
        const DWORD cbBuffer = sizeof(ACCESS_MASK) + sizeof(NDAS_DEVICE_ID);
        BYTE pbBuffer[cbBuffer];

        success = _NdasSystemCfg.GetSecureValueEx(
                      szSubcontainer,
                      _T("GrantedAccess"),
                      pbBuffer,
                      cbBuffer);

        if (success)
        {
            grantedAccess = *((ACCESS_MASK*)(pbBuffer));
        }
        grantedAccess |= GENERIC_READ; // to prevent invalid access mask configuration

        //
        // NDAS Device Name
        //

        TCHAR szDeviceName[MAX_NDAS_DEVICE_NAME_LEN + 1];
        success = _NdasSystemCfg.GetValueEx(
                      szSubcontainer,
                      _T("DeviceName"),
                      szDeviceName,
                      sizeof(TCHAR)*(MAX_NDAS_DEVICE_NAME_LEN + 1));

        if (!success)
        {
            COMVERIFY(StringCchCopy(
                          szDeviceName, RTL_NUMBER_OF(szDeviceName), _T("NDAS Device")));
        }

        //
        // Register
        //

        CComPtr<INdasDevice> pNdasDevice;
        hr = Register(
                 i,
                 regData.DeviceId,
                 regFlags,
                 ndasIdExtension,
                 CComBSTR(szDeviceName),
                 grantedAccess,
                 ndasOemCode,
                 &pNdasDevice);

        if (FAILED(hr))
        {
            //
            // This may happen due to auto-register feature!
            //
            XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                      "Registration failed for %s, hr=0x%X\n",
                      CNdasDeviceId(regData.DeviceId).ToStringA(),
                      hr);
            //
            // During bootstrapping register may fail for unsupported VID.
            // In that case, we should retain this slot number to avoid
            // overwriting the existing data which may be created by
            // the higher version.
            //
            m_slotbit[i] = true;
            continue;
        }

        BOOL fEnabled = FALSE;
        success = _NdasSystemCfg.GetValueEx(
                      szSubcontainer,
                      _T("Enabled"),
                      &fEnabled);

        if (success && fEnabled)
        {
            COMVERIFY(pNdasDevice->put_Enabled(fEnabled));
        }
    }

    //
    // Migration will be done only once
    // if there is no registered devices in the current configurations
    // and if the migration flag (Install\Migrate = 1) is set
    //
    if (m_deviceSlotMap.size() == 0)
    {
        success = _NdasSystemCfg.GetValueEx(_T("Install"), _T("Migrated"), &fMigrated);
        if (!success || !fMigrated)
        {
            fMigrated = TRUE;
            pImportLegacySettings();
            _NdasSystemCfg.SetValueEx(_T("Install"), _T("Migrated"), fMigrated);
        }
    }

    //
    // Clear bootstrapping state
    //
    m_fBootstrapping = FALSE;

    return S_OK;
}
Пример #8
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;
}
Пример #9
0
BOOL
CNdasDeviceRegistrar::pImportLegacyEntry(DWORD SlotNo, HKEY hEntryKey)
{
    static CONST size_t CB_ADDR = sizeof(TCHAR) * 18;

    HRESULT hr = E_FAIL;
    TCHAR szAddrVal[CB_ADDR + 1];
    DWORD cbAddrVal = sizeof(szAddrVal);
    DWORD dwValueType;

    LONG lResult = ::RegQueryValueEx(
                       hEntryKey,
                       _T("Address"),
                       0,
                       &dwValueType,
                       (LPBYTE)szAddrVal,
                       &cbAddrVal);

    if (ERROR_SUCCESS != lResult)
    {
        // Ignore invalid values
        return FALSE;
    }

    if (cbAddrVal != CB_ADDR)
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Invalid Entry(A): %ls, ignored\n", szAddrVal);
        return FALSE;
    }

    //
    // 00:0B:D0:00:D4:2F to NDAS_DEVICE_ID
    //

    NDAS_DEVICE_ID deviceId = {0};
    BOOL success = pConvertStringToDeviceId(szAddrVal, &deviceId);
    if (!success)
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Invalid Entry(D): %ls, ignored\n", szAddrVal);
        return FALSE;
    }

    XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
              "Importing an entry: %s\n",
              CNdasDeviceId(deviceId).ToStringA());

    TCHAR szNameVal[MAX_NDAS_DEVICE_NAME_LEN + 1] = {0};
    DWORD cbNameVal = sizeof(szNameVal);
    lResult = ::RegQueryValueEx(
                  hEntryKey,
                  _T("Name"),
                  0,
                  &dwValueType,
                  (LPBYTE)szNameVal,
                  &cbNameVal);

    if (ERROR_SUCCESS != lResult || _T('\0') == szNameVal[0])
    {
        TCHAR szDefaultName[MAX_NDAS_DEVICE_NAME_LEN + 1] = {0};
        success = _NdasSystemCfg.GetValueEx(
                      _T("Devices"),
                      _T("DefaultPrefix"),
                      szDefaultName,
                      sizeof(szDefaultName));

        if (!success)
        {
            COMVERIFY( StringCchCopy(
                           szDefaultName,
                           MAX_NDAS_DEVICE_NAME_LEN + 1,
                           _T("NDAS Device ")) );
        }

        hr = ::StringCchPrintf(
                 szNameVal,
                 MAX_NDAS_DEVICE_NAME_LEN,
                 _T("%s %d"),
                 szDefaultName,
                 SlotNo);
    }


    BYTE pbSerialKeyVal[9];
    DWORD cbSerialKeyVal = sizeof(pbSerialKeyVal);
    lResult = ::RegQueryValueEx(
                  hEntryKey,
                  _T("SerialKey"),
                  0,
                  &dwValueType,
                  (LPBYTE)pbSerialKeyVal,
                  &cbSerialKeyVal);

    if (ERROR_SUCCESS != lResult)
    {
        return FALSE;
    }

    if (cbSerialKeyVal != sizeof(pbSerialKeyVal))
    {
        return FALSE;
    }

    ACCESS_MASK fAccessMode = GENERIC_READ;
    if (0xFF == pbSerialKeyVal[8])
    {
        // Registered as RW
        fAccessMode |= GENERIC_WRITE;
    }
    else if (0x00 == pbSerialKeyVal[8])
    {
        // Registered as RO
    }
    else
    {
        // Invalid value
        return FALSE;
    }

    //
    // Register function returns the locked pointer
    //

    CComPtr<INdasDevice> pNdasDevice;

    hr = Register(
             SlotNo,
             deviceId,
             0,
             NULL,
             CComBSTR(szNameVal),
             fAccessMode,
             NULL,
             &pNdasDevice);

    if (FAILED(hr))
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Failed to register %s at %d during import, error=0x%X",
                  CNdasDeviceId(deviceId).ToStringA(), SlotNo, hr);
        return FALSE;
    }

    // Always enable this!
    COMVERIFY(pNdasDevice->put_Enabled(TRUE));

    return TRUE;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
0
BOOL
CNdasDeviceRegistrar::ImportLegacyEntry(DWORD dwSlotNo, HKEY hEntryKey)
{
	static CONST size_t CB_ADDR = sizeof(TCHAR) * 18;

	HRESULT hr = E_FAIL;
	TCHAR szAddrVal[CB_ADDR + 1];
	DWORD cbAddrVal = sizeof(szAddrVal);
	DWORD dwValueType;

	LONG lResult = ::RegQueryValueEx(
		hEntryKey, 
		_T("Address"), 
		0, 
		&dwValueType, 
		(LPBYTE)szAddrVal,
		&cbAddrVal);

	if (ERROR_SUCCESS != lResult) {
		// Ignore invalid values
		return FALSE;
	}

	if (cbAddrVal != CB_ADDR) {
		DBGPRT_ERR(_FT("Invalid Entry(A): %s, ignored\n"), szAddrVal);
		return FALSE;
	}

	//
	// 00:0B:D0:00:D4:2F to NDAS_DEVICE_ID
	//

	NDAS_DEVICE_ID deviceId = {0};
	BOOL fSuccess = pConvertStringToDeviceId(szAddrVal, &deviceId);
	if (!fSuccess) {
		DBGPRT_ERR(_FT("Invalid Entry(D): %s, ignored\n"), szAddrVal);
		return FALSE;
	}

	DBGPRT_INFO(_FT("Importing an entry: %s\n"), CNdasDeviceId(deviceId).ToString());

	TCHAR szNameVal[MAX_NDAS_DEVICE_NAME_LEN + 1] = {0};
	DWORD cbNameVal = sizeof(szNameVal);
	lResult = ::RegQueryValueEx(
		hEntryKey,
		_T("Name"),
		0,
		&dwValueType,
		(LPBYTE)szNameVal,
		&cbNameVal);

	if (ERROR_SUCCESS != lResult || _T('\0') == szNameVal[0]) {
		TCHAR szDefaultName[MAX_NDAS_DEVICE_NAME_LEN + 1] = {0};
		fSuccess = _NdasSystemCfg.GetValueEx(
			_T("Devices"), 
			_T("DefaultPrefix"),
			szDefaultName,
			sizeof(szDefaultName));

		if (!fSuccess) {
			hr = ::StringCchCopy(
				szDefaultName, 
				MAX_NDAS_DEVICE_NAME_LEN + 1,
				_T("NDAS Device "));
			_ASSERTE(SUCCEEDED(hr));
		}

		hr = ::StringCchPrintf(
			szNameVal,
			MAX_NDAS_DEVICE_NAME_LEN,
			_T("%s %d"), 
			szDefaultName, 
			dwSlotNo);
	}


	BYTE pbSerialKeyVal[9];
	DWORD cbSerialKeyVal = sizeof(pbSerialKeyVal);
	lResult = ::RegQueryValueEx(
		hEntryKey,
		_T("SerialKey"),
		0,
		&dwValueType,
		(LPBYTE)pbSerialKeyVal,
		&cbSerialKeyVal);

	if (ERROR_SUCCESS != lResult) {
		return FALSE;
	}

	if (cbSerialKeyVal != sizeof(pbSerialKeyVal)) {
		return FALSE;
	}

	ACCESS_MASK fAccessMode = GENERIC_READ;
	if (0xFF == pbSerialKeyVal[8]) {
		// Registered as RW
		fAccessMode |= GENERIC_WRITE;
	} else if (0x00 == pbSerialKeyVal[8]) {
		// Registered as RO
	} else {
		// Invalid value
		return FALSE;
	}

	PCNdasDevice pDevice = Register(deviceId, dwSlotNo);

	if (NULL == pDevice) {
		DBGPRT_ERR_EX(_FT("Failed to register %s at %d during import: "),
			CNdasDeviceId(deviceId).ToString(),
			dwSlotNo);
		return FALSE;
	}

	// Always enable this!
	pDevice->Enable(TRUE);
	pDevice->SetName(szNameVal);
	pDevice->SetGrantedAccess(fAccessMode);

	return TRUE;
}
Пример #14
0
CNdasDevicePtr
CNdasDeviceRegistrar::Register(
	__in_opt DWORD SlotNo,
	__in const NDAS_DEVICE_ID& DeviceId,
	__in DWORD RegFlags,
	__in_opt const NDASID_EXT_DATA* NdasIdExtension)
{
	//
	// this will lock this class from here
	// and releases the lock when the function returns;
	//
	InstanceAutoLock autolock(this);
	
	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_DEFAULT != NdasIdExtension->VID)
	{
		XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
			"Unknown Vendor ID=0x%02X\n",
			NdasIdExtension->VID);

		::SetLastError(NDASSVC_ERROR_UNKNOWN_VENDOR_ID);
		return CNdasDevicePtr();
	}

	// If SlotNo is zero, automatically assign it.
	// check slot number
	if (0 == SlotNo)
	{
		SlotNo = LookupEmptySlot();
		if (0 == SlotNo)
		{
			return CNdasDevicePtr();
		}
	}
	else if (SlotNo > m_dwMaxSlotNo)
	{
		::SetLastError(NDASSVC_ERROR_INVALID_SLOT_NUMBER);
		return CNdasDevicePtr();
	}

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

	// find an duplicate address
	{
		CNdasDevicePtr pExistingDevice = Find(DeviceId);
		if (0 != pExistingDevice.get()) 
		{
			::SetLastError(NDASSVC_ERROR_DUPLICATE_DEVICE_ENTRY);
			return CNdasDevicePtr();
		}
	}

	// register 
	CNdasDevicePtr pDevice(new CNdasDevice(SlotNo, DeviceId, RegFlags, NdasIdExtension));
	if (0 == pDevice.get()) 
	{
		// memory allocation failed
		// No need to set error here!
		return CNdasDevicePtr();
	}

	BOOL fSuccess = pDevice->Initialize();
	if (!fSuccess) 
	{
		XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
			"Device initialization failed, error=0x%X\n", GetLastError());
		return CNdasDevicePtr();
	}

	m_slotbit[SlotNo] = true;

	bool insertResult;

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

	XTLVERIFY( m_deviceIdMap.insert(std::make_pair(DeviceId, pDevice)).second );
	//DeviceIdMap::value_type(DeviceId, pDevice)).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
	{
		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 = DeviceId;
			regData.NdasIdExtension = *NdasIdExtension;

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

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

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

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

	//
	// During bootstrapping, we do not publish this event
	// Bootstrap process will publish an event later
	//
	if (!m_fBootstrapping) 
	{
		(void) m_service.GetEventPublisher().DeviceEntryChanged();
	}

	return pDevice;
}
Пример #15
0
BOOL
CNdasDeviceRegistrar::Bootstrap()
{
	BOOL fSuccess = FALSE;
	BOOL fMigrated = FALSE;

	//
	// Set bootstrapping flag to prevent multiple events 
	// for DeviceSetChange Events
	//

	m_fBootstrapping = TRUE;

	TCHAR szSubcontainer[30] = {0};
	for (DWORD i = 0; i < MAX_SLOT_NUMBER; ++i) 
	{
		COMVERIFY(StringCchPrintf(
			szSubcontainer, 30, _T("%s\\%04d"), CFG_CONTAINER, i));

		BOOL fAutoRegistered = FALSE;
		fSuccess = _NdasSystemCfg.GetValueEx(
			szSubcontainer,
			_T("AutoRegistered"),
			&fAutoRegistered);

		if (fSuccess && fAutoRegistered)
		{
			XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
				"Deleting %ls\n", szSubcontainer);
			// Auto registered devices are not persistent
			// it is an error to show up here.
			// We just ignore those entries
			fSuccess = _NdasSystemCfg.DeleteContainer(szSubcontainer, TRUE);
			if (!fSuccess)
			{
				XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
					"Deleting a RegKey=%ls failed, error=0x%X\n", 
					szSubcontainer, GetLastError());
			}
			continue;
		}

		DWORD cbUsed;

		NDAS_DEVICE_ID_REG_DATA regData = {0};
		const NDASID_EXT_DATA* ndasIdExtension = NULL;

		fSuccess = _NdasSystemCfg.GetSecureValueEx(
			szSubcontainer, 
			_T("DeviceID2"),
			&regData,
			sizeof(NDAS_DEVICE_ID_REG_DATA),
			&cbUsed);

		if (!fSuccess) 
		{
			//
			// Non-extension data
			//
			fSuccess = _NdasSystemCfg.GetSecureValueEx(
				szSubcontainer, 
				_T("DeviceID"),
				&regData.DeviceId,
				sizeof(regData.DeviceId),
				&cbUsed);

			//
			// ignore read fault - tampered or not exists
			//
			if (!fSuccess || cbUsed != sizeof(NDAS_DEVICE_ID))
			{
				continue;
			}
			if (regData.DeviceId.VID == 0) {
				// Assume VID 0 is VID 1 to support registry entry created by older software(~3.11)
				regData.DeviceId.VID = 1;
			}
		}
		else
		{
			if (cbUsed != sizeof(NDAS_DEVICE_ID_REG_DATA))
			{
				//
				// maybe more recent versions, unrecognized, ignore
				//
				continue;
			}
			ndasIdExtension = &regData.NdasIdExtension;
		}

		DWORD regFlags;
		fSuccess = _NdasSystemCfg.GetSecureValueEx(
			szSubcontainer,
			_T("RegFlags"),
			&regFlags,
			sizeof(regFlags));

		if (!fSuccess)
		{
			regFlags = NDAS_DEVICE_REG_FLAG_NONE;
		}

		CNdasDevicePtr pDevice = Register(
			i, 
			regData.DeviceId, 
			regFlags,
			ndasIdExtension);

		// This may happen due to auto-register feature!
		if (CNdasDeviceNullPtr == pDevice) 
		{
			XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
				"Registration failed for %s, error=0x%X\n",
				CNdasDeviceId(regData.DeviceId).ToStringA(),
				GetLastError());
			//
			// During bootstrapping register may fail for unsupported VID.
			// In that case, we should retain this slot number to avoid
			// overwriting the existing data which may be created by
			// the higher version.
			//
			m_slotbit[i] = true;
			continue;
		}

		NDAS_OEM_CODE oemCode;
		fSuccess = _NdasSystemCfg.GetSecureValueEx(
			szSubcontainer,
			_T("OEMCode"),
			&oemCode,
			sizeof(NDAS_OEM_CODE),
			&cbUsed);

		if (fSuccess && cbUsed == sizeof(NDAS_OEM_CODE))
		{
			pDevice->SetOemCode(oemCode);
		}

		ACCESS_MASK grantedAccess = GENERIC_READ;
		const DWORD cbBuffer = sizeof(ACCESS_MASK) + sizeof(NDAS_DEVICE_ID);
		BYTE pbBuffer[cbBuffer];
		
		fSuccess = _NdasSystemCfg.GetSecureValueEx(
			szSubcontainer,
			_T("GrantedAccess"),
			pbBuffer,
			cbBuffer);

		if (fSuccess) 
		{
			grantedAccess = *((ACCESS_MASK*)(pbBuffer));
		}
		grantedAccess |= GENERIC_READ; // to prevent invalid access mask configuration
		// XTLASSERT(grantedAccess & GENERIC_READ); // invalid configuration?
		pDevice->SetGrantedAccess(grantedAccess);

		TCHAR szDeviceName[MAX_NDAS_DEVICE_NAME_LEN + 1];
		fSuccess = _NdasSystemCfg.GetValueEx(
			szSubcontainer, 
			_T("DeviceName"),
			szDeviceName,
			sizeof(TCHAR)*(MAX_NDAS_DEVICE_NAME_LEN + 1));

		if (fSuccess) 
		{
			pDevice->SetName(szDeviceName);
		}

		BOOL fEnabled = FALSE;
		fSuccess = _NdasSystemCfg.GetValueEx(
			szSubcontainer,
			_T("Enabled"),
			&fEnabled);

		if (fSuccess && fEnabled) 
		{
			pDevice->Enable(fEnabled);
		}
	}

	//
	// Migration will be done only once 
	// if there is no registered devices in the current configurations
	// and if the migration flag (Install\Migrate = 1) is set
	//
	if (m_deviceSlotMap.size() == 0) 
	{
		fSuccess = _NdasSystemCfg.GetValueEx(_T("Install"), _T("Migrated"), &fMigrated);
		if (!fSuccess || !fMigrated) 
		{
			fMigrated = TRUE;
			ImportLegacySettings();
			_NdasSystemCfg.SetValueEx(_T("Install"), _T("Migrated"), fMigrated);
		}
	}

	//
	// Clear bootstrapping state
	//
	m_fBootstrapping = FALSE;

	return TRUE;
}