BOOL CNdasUnitDevice::UnregisterFromLDM() { ximeta::CAutoLock autolock(this); CNdasLogicalDeviceManager* pLDM = pGetNdasLogicalDeviceManager(); BOOL fSuccess = pLDM->Unregister(*this); m_pLogicalDevice->Release(); _ASSERTE(fSuccess); return fSuccess; }
bool CNdasUnitDevice::UnregisterFromLogicalDeviceManager() { InstanceAutoLock autolock(this); CNdasLogicalDeviceManager& manager = pGetNdasLogicalDeviceManager(); if (manager.Unregister(shared_from_this())) { m_pLogicalDevice.reset(); return true; } return false; }
bool CNdasUnitDevice::RegisterToLogicalDeviceManager() { InstanceAutoLock autolock(this); CNdasLogicalDeviceManager& manager = pGetNdasLogicalDeviceManager(); m_pLogicalDevice = manager.Register(shared_from_this()); if (CNdasLogicalDeviceNullPtr == m_pLogicalDevice) { XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR, "Failed to register a unit device to the LDM, error=0x%X\n", GetLastError()); return false; } return true; }
DWORD CNdasService::OnServiceShutdown() { DBGPRT_INFO(_FT("System is shutting down...\n")); ReportStatusToSCMgr(SERVICE_STOP_PENDING, 1000); CNdasLogicalDeviceManager* pLogDevMan = pGetNdasLogicalDeviceManager(); pLogDevMan->OnShutdown(); ReportStatusToSCMgr(SERVICE_STOP_PENDING, 1000); (VOID) ::LfsFiltCtlShutdown(); // TODO: Do I have to stop here? this->Stop(); return NO_ERROR; }
BOOL CNdasLogicalDevice::cpCheckPlugInCondForDVD(ACCESS_MASK requestingAccess) { CNdasLogicalDeviceManager* pLdm = pGetNdasLogicalDeviceManager(); CNdasLogicalDeviceCollection coll; pLdm->Lock(); pLdm->GetItems(coll); pLdm->Unlock(); int mounted = std::count_if( coll.begin(), coll.end(), IsLogicalDVDMountedAsRW); if (mounted > 0) { ::SetLastError(NDASHLPSVC_ERROR_NO_MORE_DVD_WRITE_ACCESS_INSTANCE_ALLOWED); return FALSE; } return TRUE; }
BOOL CNdasUnitDevice::RegisterToLDM() { ximeta::CAutoLock autolock(this); CNdasLogicalDeviceManager* pLDM = pGetNdasLogicalDeviceManager(); // // Support auto-registered devices // ACCESS_MASK acMountOnReady = 0; if (m_pParentDevice->GetAutoRegistered()) { acMountOnReady = m_pParentDevice->GetGrantedAccess(); } m_pLogicalDevice = pLDM->Register(*this, acMountOnReady, FALSE); if (NULL == m_pLogicalDevice) { DBGPRT_ERR_EX(_FT("Failed to register a unit device to the LDM: ")); return FALSE; } return TRUE; }
// // 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; }
// // 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; }
BOOL CNdasIXBcast::BroadcastStatus() { NDASSCSI_QUERY_INFO_DATA NdasScsiQuery; NDSCIOCTL_PRIMUNITDISKINFO LurInformation; CNdasLogicalDeviceManager& manager = pGetNdasLogicalDeviceManager(); CNdasLogicalDeviceVector logDevices; manager.Lock(); manager.GetItems(logDevices); manager.Unlock(); for (CNdasLogicalDeviceVector::const_iterator itr = logDevices.begin(); itr != logDevices.end(); ++itr) { CNdasLogicalDevicePtr pLogDevice = *itr; if (NDAS_LOGICALDEVICE_STATUS_MOUNTED != pLogDevice->GetStatus()) { continue; } CONST NDAS_LOCATION& location = pLogDevice->GetNdasLocation(); NdasScsiQuery.InfoClass = NdscPrimaryUnitDiskInformation; NdasScsiQuery.Length = sizeof(NDASSCSI_QUERY_INFO_DATA); NdasScsiQuery.NdasScsiAddress.SlotNo = location; NdasScsiQuery.QueryDataLength = 0; XTL::AutoFileHandle handle = pOpenStorageDeviceByNumber( pLogDevice->GetDeviceNumberHint(), GENERIC_WRITE|GENERIC_READ); BOOL fSuccess = NdasPortCtlQueryInformation( handle, &NdasScsiQuery, sizeof(NDASSCSI_QUERY_INFO_DATA), &LurInformation, sizeof(NDSCIOCTL_PRIMUNITDISKINFO)); if (!fSuccess) { XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR, "LanscsiQueryInformation failed, slot=%d, error=0x%X\n", location, GetLastError()); continue; } // // Broadcast a primary write access status // if (LurInformation.Lur.DeviceMode == DEVMODE_SHARED_READWRITE && !(LurInformation.Lur.EnabledFeatures & NDASFEATURE_SECONDARY)) { const DWORD cbBuffer = sizeof(LSINFOX_HEADER) + sizeof(LSINFOX_PRIMARY_UPDATE); BYTE lpbBuffer[cbBuffer] = {0}; PLSINFOX_HEADER pixHeader = reinterpret_cast<PLSINFOX_HEADER>(lpbBuffer); PLSINFOX_DATA pixData = reinterpret_cast<PLSINFOX_DATA>(lpbBuffer + sizeof(LSINFOX_HEADER)); // // CAUTION: InfoExchange Protocol uses little-endian (Intel) // // // Header // UCHAR ixProtocolName[4] = INFOX_DATAGRAM_PROTOCOL; ::CopyMemory(pixHeader->Protocol, ixProtocolName, 4); pixHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER; pixHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER; pixHeader->OsMajorType = OSTYPE_WINDOWS; DWORD dwOSMajorVersion, dwOSMinorVersion; pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion); USHORT usLfsOsMinorType = pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion); pixHeader->OsMinorType = usLfsOsMinorType; pixHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE; pixHeader->MessageSize = cbBuffer; // // Data // // primary node is dependent to each interface pixData->Update.PrimaryNode; pixData->Update.PrimaryPort = LPXRP_LFS_PRIMARY; pixData->Update.SWMajorVersion = NDASIX_VERSION_MAJOR; // TODO: Change these values pixData->Update.SWMinorVersion = NDASIX_VERSION_MINOR; pixData->Update.SWBuildNumber = NDASIX_VERSION_BUILD; pixData->Update.NDFSCompatVersion = m_NDFSVersion.wMajor; pixData->Update.NDFSVersion = m_NDFSVersion.wMinor; // // NetDisk Node is a property of each unit device // pixData->Update.NetDiskNode; // // We have fixed the port // (CNdasDevice does not store Port Number internally) // Do not try to retrieve from GetRemoteLpxAddress() // pixData->Update.NetDiskPort = NDAS_DEVICE_LPX_PORT; // // Unit Disk Number is a property of each unit device // pixData->Update.UnitDiskNo; // // pLogDevice->GetStatus() // for (DWORD n = 0; n < pLogDevice->GetUnitDeviceCount(); ++n) { // // Actually, we should traverse the real entry // from the device registrar. // However, here we do the shortcut for using NDAS device id // and fixed NetDiskPort, etc. // NDAS_UNITDEVICE_ID unitDeviceId = pLogDevice->GetUnitDeviceID(n); C_ASSERT(sizeof(pixData->Update.NetDiskNode) == sizeof(unitDeviceId.DeviceId.Node)); ::CopyMemory( pixData->Update.NetDiskNode, unitDeviceId.DeviceId.Node, sizeof(pixData->Update.NetDiskNode)); pixData->Update.UnitDiskNo = static_cast<USHORT>(unitDeviceId.UnitNo); // // Broadcast the data to every interface // for (DWORD i = 0; i < MAX_SOCKETLPX_INTERFACE; ++i) { if (INVALID_SOCKET != (SOCKET) m_senders[i]) { // // Fill the Primary Node (LPX Address Node) // LPX_ADDRESS localLpxAddress = m_senders[i].GetBoundAddr()->LpxAddress; C_ASSERT(sizeof(pixData->Update.PrimaryNode) == sizeof(localLpxAddress.Node)); ::CopyMemory( pixData->Update.PrimaryNode, localLpxAddress.Node, sizeof(pixData->Update.PrimaryNode)); // // Send the data // DWORD cbSent = 0; BOOL fSuccess = m_senders[i].SendToSync( &NDASIX_BCAST_ADDR, cbBuffer, lpbBuffer, 0, &cbSent); if (!fSuccess) { XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR, "SendToSync failed, bytes=%d, error=0x%X\n", cbBuffer, GetLastError()); } } // end if } // for each local LPX address } // for each unit device } // if the logical device has a primary write access. } // for each logical device return TRUE; }
BOOL CNdasIXBcast::BroadcastStatus() { BUSENUM_QUERY_INFORMATION BusEnumQuery; BUSENUM_INFORMATION BusEnumInformation; CNdasLogicalDeviceManager* pLdm = pGetNdasLogicalDeviceManager(); CNdasLogicalDeviceCollection coll; pLdm->Lock(); pLdm->GetItems(coll); pLdm->Unlock(); for (CNdasLogicalDeviceCollection::const_iterator itr = coll.begin(); itr != coll.end(); ++itr) { CNdasLogicalDevice* pLogDevice = *itr; if (NDAS_LOGICALDEVICE_STATUS_MOUNTED != pLogDevice->GetStatus()) { continue; } CONST NDAS_SCSI_LOCATION& location = pLogDevice->GetNdasScsiLocation(); BusEnumQuery.InfoClass = INFORMATION_PDO; BusEnumQuery.Size = sizeof(BUSENUM_QUERY_INFORMATION); BusEnumQuery.SlotNo = location.SlotNo; BOOL fSuccess = LsBusCtlQueryInformation( &BusEnumQuery, sizeof(BUSENUM_QUERY_INFORMATION), &BusEnumInformation, sizeof(BUSENUM_INFORMATION)); if (!fSuccess) { DPErrorEx(_FT("LanscsiQueryInformation failed at slot %d: "), location.SlotNo); continue; } // // Broadcast a primary write access status // if (ND_ACCESS_ISRW(BusEnumInformation.PdoInfo.GrantedAccess)) { const DWORD cbBuffer = sizeof(LSINFOX_HEADER) + sizeof(LSINFOX_PRIMARY_UPDATE); BYTE lpbBuffer[cbBuffer] = {0}; PLSINFOX_HEADER pixHeader = reinterpret_cast<PLSINFOX_HEADER>(lpbBuffer); PLSINFOX_DATA pixData = reinterpret_cast<PLSINFOX_DATA>(lpbBuffer + sizeof(LSINFOX_HEADER)); // // CAUTION: InfoExchange Protocol uses little-endian (Intel) // // // Header // UCHAR ixProtocolName[4] = INFOX_DATAGRAM_PROTOCOL; ::CopyMemory(pixHeader->Protocol, ixProtocolName, 4); pixHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER; pixHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER; pixHeader->OsMajorType = OSTYPE_WINDOWS; DWORD dwOSMajorVersion, dwOSMinorVersion; pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion); USHORT usLfsOsMinorType = pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion); pixHeader->OsMinorType = usLfsOsMinorType; pixHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE; pixHeader->MessageSize = cbBuffer; // // Data // // primary node is dependent to each interface pixData->Update.PrimaryNode; pixData->Update.PrimaryPort = LPXRP_LFS_PRIMARY; pixData->Update.SWMajorVersion = NDASIX_VERSION_MAJOR; // TODO: Change these values pixData->Update.SWMinorVersion = NDASIX_VERSION_MINOR; pixData->Update.SWBuildNumber = NDASIX_VERSION_BUILD; pixData->Update.NDFSCompatVersion = m_NDFSVersion.wMajor; pixData->Update.NDFSVersion = m_NDFSVersion.wMinor; // // NetDisk Node is a property of each unit device // pixData->Update.NetDiskNode; // // We have fixed the port // (CNdasDevice does not store Port Number internally) // Do not try to retrieve from GetRemoteLpxAddress() // pixData->Update.NetDiskPort = NDAS_DEVICE_LPX_PORT; // // Unit Disk Number is a property of each unit device // pixData->Update.UnitDiskNo; // // pLogDevice->GetStatus() // for (DWORD n = 0; n < pLogDevice->GetUnitDeviceCount(); ++n) { // // Actually, we should traverse the real entry // from the device registrar. // However, here we do the shortcut for using NDAS device id // and fixed NetDiskPort, etc. // NDAS_UNITDEVICE_ID unitDeviceId = pLogDevice->GetUnitDeviceID(n); _ASSERTE(sizeof(pixData->Update.NetDiskNode) == sizeof(unitDeviceId.DeviceId)); ::CopyMemory( pixData->Update.NetDiskNode, unitDeviceId.DeviceId.Node, sizeof(pixData->Update.NetDiskNode)); pixData->Update.UnitDiskNo = unitDeviceId.UnitNo; // // Broadcast the data to every interface // for (DWORD i = 0; i < MAX_SOCKETLPX_INTERFACE; ++i) { if (INVALID_SOCKET != (SOCKET) m_senders[i]) { // // Fill the Primary Node (LPX Address Node) // LPX_ADDRESS localLpxAddress = m_senders[i].GetBoundAddr()->LpxAddress; _ASSERTE(sizeof(pixData->Update.PrimaryNode) == sizeof(localLpxAddress.Node)); ::CopyMemory( pixData->Update.PrimaryNode, localLpxAddress.Node, sizeof(pixData->Update.PrimaryNode)); // // Send the data // DWORD cbSent = 0; BOOL fSuccess = m_senders[i].SendToSync( &NDASIX_BCAST_ADDR, cbBuffer, lpbBuffer, 0, &cbSent); if (!fSuccess) { DPWarningEx(_FT("Sending a packet failed: ")); } } // end if } // for each local LPX address } // for each unit device } // if the logical device has a primary write access. } // for each logical device return TRUE; }