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); }
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); }
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; }
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); }
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; }
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(); } }
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"), ®Data, sizeof(NDAS_DEVICE_ID_REG_DATA), &cbUsed); if (!success) { // // Non-extension data // success = _NdasSystemCfg.GetSecureValueEx( szSubcontainer, _T("DeviceID"), ®Data.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 = ®Data.NdasIdExtension; } // // RegFlags // DWORD regFlags; success = _NdasSystemCfg.GetSecureValueEx( szSubcontainer, _T("RegFlags"), ®Flags, 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; }
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"), ®Data, 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; }
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; }
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; }
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; }
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; }
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; }
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"), ®Data, 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; }
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"), ®Data, sizeof(NDAS_DEVICE_ID_REG_DATA), &cbUsed); if (!fSuccess) { // // Non-extension data // fSuccess = _NdasSystemCfg.GetSecureValueEx( szSubcontainer, _T("DeviceID"), ®Data.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 = ®Data.NdasIdExtension; } DWORD regFlags; fSuccess = _NdasSystemCfg.GetSecureValueEx( szSubcontainer, _T("RegFlags"), ®Flags, 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; }