Пример #1
0
void
CNdasLogicalDeviceManager::ShutdownOf(
	const CNdasLogicalDeviceManager::LDIDMap::value_type& pair)
{
	CNdasLogicalDevice* pLogicalDevice = pair.second;
	pLogicalDevice->OnShutdown();
}
Пример #2
0
CNdasLogicalDevice*
CNdasLogicalDeviceManager::Find(CONST NDAS_SCSI_LOCATION& location)
{
	ximeta::CAutoLock autolock(this);

	LocationMap::const_iterator citr = m_NdasScsiLocationMap.find(location);
	if (m_NdasScsiLocationMap.end() == citr) {
		return NULL;
	}
	CNdasLogicalDevice* pLogicalDevice = citr->second;
	if (NULL != pLogicalDevice) pLogicalDevice->AddRef();
	return pLogicalDevice;
}
Пример #3
0
CNdasLogicalDevice*
CNdasLogicalDeviceManager::Find(NDAS_LOGICALDEVICE_ID ldid)
{
	ximeta::CAutoLock autolock(this);

	LDIDMap::const_iterator citr = m_LDIDMap.find(ldid);
	if (m_LDIDMap.end() == citr) {
		return NULL;
	}
	CNdasLogicalDevice* pLogicalDevice = citr->second;
	if (NULL != pLogicalDevice) pLogicalDevice->AddRef();
	return pLogicalDevice;
}
Пример #4
0
CNdasLogicalDevice* 
CNdasLogicalDeviceManager::Register(CNdasUnitDevice& unitDevice)
{
	ximeta::CAutoLock autolock(this);

	CONST NDAS_LOGICALDEVICE_GROUP& ldGroup = unitDevice.GetLDGroup();
	DWORD ldSequence = unitDevice.GetLDSequence();

	CNdasLogicalDevice* pLogDevice = NULL;
	LDGroupMap::iterator itr = m_LDGroupMap.find(ldGroup);

	if (itr == m_LDGroupMap.end()) {
		//
		// New Logical Device Instance
		//
		NDAS_LOGICALDEVICE_ID id = cpAllocateID();
		if (0 == id) {
			// SLOT FULL
			::SetLastError(NDASSVC_ERROR_LOGICALDEVICE_SLOT_FULL);
			return NULL;
		}

		pLogDevice = new CNdasLogicalDevice(id, ldGroup);
		if (NULL == pLogDevice) {
			::SetLastError(ERROR_OUTOFMEMORY);
			return NULL;
		}
		BOOL fSuccess = pLogDevice->Initialize();
		if (!fSuccess) {
			delete pLogDevice;
			return NULL;
		}
		pLogDevice->AddRef(); // internal pointer reference
		m_LDGroupMap.insert(LDGroupMap::value_type(ldGroup, pLogDevice));
		m_LDIDMap.insert(LDIDMap::value_type(id, pLogDevice));

		CRefObjPtr<CNdasDevice> pDevice = unitDevice.GetParentDevice();
		_ASSERTE(NULL != pDevice.p);
		if (pDevice->IsAutoRegistered()) {
			pLogDevice->SetMountOnReady(pDevice->GetGrantedAccess());
			// auto registered devices always ignore RiskyMountFlag
			pLogDevice->SetRiskyMountFlag(FALSE);
		}

	} else {
		pLogDevice = itr->second;
	}

	BOOL fSuccess = pLogDevice->AddUnitDevice(unitDevice);
	_ASSERTE(fSuccess);
	if (!fSuccess) {
		return NULL;
	}

	if (NULL != pLogDevice) pLogDevice->AddRef(); // external pointer reference
	return pLogDevice;
}
Пример #5
0
BOOL
CNdasLogicalDeviceManager::Unregister(CNdasUnitDevice& unitDevice)
{
	ximeta::CAutoLock autolock(this);

	CNdasLogicalDevice* pLogDevice = unitDevice.GetLogicalDevice();
	if (NULL == pLogDevice) {
		return FALSE;
	}

	DWORD ldSequence = unitDevice.GetLDSequence();
	pLogDevice->RemoveUnitDevice(unitDevice);

	if (pLogDevice->GetUnitDeviceInstanceCount() == 0) {

		NDAS_LOGICALDEVICE_ID id = pLogDevice->GetLogicalDeviceId();

		LDGroupMap::size_type ldg_erased = 
			m_LDGroupMap.erase(pLogDevice->GetLDGroup());
		_ASSERTE(1 == ldg_erased);

		LDIDMap::size_type id_erased = 
			m_LDIDMap.erase(id);
		_ASSERTE(1 == id_erased);
		
		pLogDevice->Release();

		BOOL fSuccess = cpDeallocateID(id);
		_ASSERTE(fSuccess);
	}

	return TRUE;
}
Пример #6
0
BOOL CNdasEventMonitor::OnLogicalDeviceDisconnected(DWORD nWaitIndex)
{
	ximeta::CAutoLock autolock(this);

	CNdasLogicalDevice* 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();

	DBGPRT_INFO(_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;
}
Пример #7
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) {
		DBGPRT_ERR_EX(_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;

		CNdasLogicalDeviceVector::const_iterator itr = m_vLogDevices.begin();
		for (DWORD i = 3; itr != m_vLogDevices.end(); ++itr, ++i) {
			CNdasLogicalDevice* pLogDevice = *itr;
			hWaitingHandles[i] = pLogDevice->GetDisconnectEvent();
			hWaitingHandles[dwLogDevices + i] = pLogDevice->GetAlarmEvent();
		}
		this->Unlock();

		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) {

				ximeta::CAutoLock autolock(this);

				//
				// Heartbeat Monitor Timer Event
				//
				CNdasDeviceSet::const_iterator devitr = m_hbMonDevices.begin();
				m_bIterating = TRUE;
				for (; devitr != m_hbMonDevices.end();) {
					CNdasDevice* pDevice = *devitr;
					BOOL fDetach = pDevice->OnStatusCheck();
					if (fDetach) {
						devitr = m_hbMonDevices.erase(devitr);
						pDevice->Release();
					} else {
						++devitr;
					}
				}
				m_bIterating = FALSE;

				//
				// Check the logical devices
				//
				std::for_each(
					m_vLogDevices.begin(),
					m_vLogDevices.end(),
					NdasLogicalDeviceStatusCheck);

			} else if (WAIT_OBJECT_0 + 3 <= dwWaitResult &&
				dwWaitResult < WAIT_OBJECT_0 + 3 + dwLogDevices)
			{
				//
				// Disconnect Event
				//
				DWORD n = dwWaitResult - (WAIT_OBJECT_0 + 3);
				BOOL fHandled = OnLogicalDeviceDisconnected(n);
				if (!fHandled) {
					fSuccess = ::ResetEvent(hWaitingHandles[dwWaitResult - WAIT_OBJECT_0]);
					_ASSERTE(fSuccess);
				}

			} 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);
				BOOL fHandled = OnLogicalDeviceAlarmed(n);
				if (!fHandled) {
					fSuccess = ::ResetEvent(hWaitingHandles[dwWaitResult - WAIT_OBJECT_0]);
					_ASSERTE(fSuccess);
				}

			} else {
//				_ASSERTE(FALSE);
				// Some handles may be already invalid.
				// LogicalDeviceSetChange Event
				//
				bResetLogDeviceSet = TRUE;
				DBGPRT_ERR_EX(_FT("Wait failed: "));
			}

		} while (!bResetLogDeviceSet && !bTerminateThread);

		delete [] hWaitingHandles;

	} while (!bTerminateThread);

	fSuccess = ::CancelWaitableTimer(m_hHeartbeatMonitorTimer);
	if (!fSuccess) {
		DBGPRT_ERR_EX(_FT("Canceling waitable timer failed: "));
	}

	return 0;
}
Пример #8
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;
}
Пример #9
0
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;
}
Пример #10
0
VOID
CNdasIXServer::OnIXUsageRequest(
	CLpxDatagramSocket& sock,
	CONST SOCKADDR_LPX* pRemoteAddr,
	CONST LSINFOX_NDASDEV_USAGE_REQUEST* pData)
{
	NDAS_UNITDEVICE_ID unitDeviceId = {
		{ 
			pData->NetDiskNode[0], pData->NetDiskNode[1],
			pData->NetDiskNode[2], pData->NetDiskNode[3],
			pData->NetDiskNode[4], pData->NetDiskNode[5]
		},
		pData->UnitDiskNo
	};

	DPNoise(_FT("LSINFOX_PRIMARY_USAGE_MESSAGE: %02X:%02X:%02X:%02X:%02X:%02X@%d\n"),
		pData->NetDiskNode[0],
		pData->NetDiskNode[1],
		pData->NetDiskNode[2],
		pData->NetDiskNode[3],
		pData->NetDiskNode[4],
		pData->NetDiskNode[5],
		pData->UnitDiskNo);

	CNdasLogicalDevice* pLogDevice = pGetNdasLogicalDevice(unitDeviceId);
	if (NULL == pLogDevice) {
		// Discard message
		return;
	}

	switch (pLogDevice->GetStatus()) {
	case NDAS_LOGICALDEVICE_STATUS_MOUNTED:
	case NDAS_LOGICALDEVICE_STATUS_MOUNT_PENDING:
	case NDAS_LOGICALDEVICE_STATUS_UNMOUNT_PENDING:
		break;
	default:
		//
		// Otherwise, discard message
		//
		return;
	}

	ACCESS_MASK mountedAcces = pLogDevice->GetMountedAccess();
	
	CONST DWORD cbPacket = 
		sizeof(LSINFOX_HEADER) + 
		sizeof(LSINFOX_NDASDEV_USAGE_REPLY) +
		MAX_HOSTNAME_LEN * sizeof(WCHAR);

	BYTE pbPacket[cbPacket] = {0};

	PLSINFOX_HEADER pHeader = 
		reinterpret_cast<PLSINFOX_HEADER>(pbPacket);

	PLSINFOX_NDASDEV_USAGE_REPLY pUsageReply = 
		reinterpret_cast<PLSINFOX_NDASDEV_USAGE_REPLY>(
		pbPacket + sizeof(LSINFOX_HEADER));

	//
	// Header
	//
	CONST BYTE NdasIxProtocolName[] = INFOX_DATAGRAM_PROTOCOL; 
	
	::CopyMemory(
		pHeader->Protocol, 
		NdasIxProtocolName, 
		sizeof(NdasIxProtocolName));

	pHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER;
	pHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER;
	pHeader->OsMajorType = OSTYPE_WINDOWS;

	DWORD dwOSMajorVersion, dwOSMinorVersion;
	pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion);
	USHORT usLfsOsMinorType = 
		pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion);

	pHeader->OsMinorType = usLfsOsMinorType;
	pHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE | LSINFOX_TYPE_REPLY;
	pHeader->MessageSize = cbPacket;

	//
	// Body
	//

	LPX_ADDRESS localLpxAddress = sock.GetBoundAddr()->LpxAddress;

	pUsageReply->HostLanAddr.AddressType = LSNODE_ADDRTYPE_ETHER;
	pUsageReply->HostLanAddr.AddressLen = LPXADDR_NODE_LENGTH;
	::CopyMemory(
		pUsageReply->HostLanAddr.Address,
		localLpxAddress.Node,
		LPXADDR_NODE_LENGTH);

	WCHAR wszHostName[MAX_HOSTNAME_LEN] = {0};
	USHORT hostNameType = LSNODENAME_DNSFULLYQ;
	DWORD cchHostName = MAX_HOSTNAME_LEN;
	
	BOOL fSuccess = ::GetComputerNameExW(
		ComputerNameDnsFullyQualified,
		wszHostName,
		&cchHostName);

	if (!fSuccess) {
		hostNameType = LSNODENAME_NETBOIS;
		cchHostName = MAX_HOSTNAME_LEN;
		fSuccess = ::GetComputerNameExW(
			ComputerNameNetBIOS,
			wszHostName,
			&cchHostName);
	}

	if (!fSuccess) {
		hostNameType = LSNODENAME_UNKNOWN;
		cchHostName = 0;
	}

	pUsageReply->HostNameType = hostNameType;
	pUsageReply->HostNameLength = cchHostName;
	::CopyMemory(
		pUsageReply->HostName,
		wszHostName,
		cchHostName * sizeof(WCHAR));

	//
	// LPX Address.Node is an adapter address.
	//
	const DWORD cbAdapterAddress = 6;
	BYTE pAdapterAddress[cbAdapterAddress] = {0};
	::CopyMemory(pAdapterAddress, localLpxAddress.Node, 6);

	DWORD cbIpAddress = 14; // TODO: why is this 14?
	BYTE pPrimaryIpAddress[14] = {0};

	fSuccess = pGetAdapterPrimaryIpAddress(
		cbAdapterAddress, 
		pAdapterAddress,
		&cbIpAddress,
		pPrimaryIpAddress);

	fSuccess = FALSE;

	if (!fSuccess) {

		DBGPRT_WARN_EX(_FT("Failed to get primary ip address of %s: "),
			CSockLpxAddr(sock.GetBoundAddr()).ToString());

		pUsageReply->HostWanAddr.AddressLen = 0;
		pUsageReply->HostWanAddr.AddressType = LSNODE_ADDRTYPE_IP;
		::ZeroMemory(pUsageReply->HostWanAddr.Address, LSNODE_ADDR_LENGTH);

	} else {
		pUsageReply->HostWanAddr.AddressLen = (USHORT) cbIpAddress;
		pUsageReply->HostWanAddr.AddressType = LSNODE_ADDRTYPE_IP;
		_ASSERTE(cbIpAddress <= LSNODE_ADDR_LENGTH);
		::CopyMemory(
			pUsageReply->HostWanAddr.Address,
			pPrimaryIpAddress, 
			cbIpAddress);
	}

	//
	// Software Versions, status, etc
	//
	if (mountedAcces & GENERIC_READ) {
		pUsageReply->AccessRight |= LSSESSION_ACCESS_READ;
	}
	if (mountedAcces & GENERIC_WRITE) {
		pUsageReply->AccessRight |= LSSESSION_ACCESS_WRITE;
	}

	pUsageReply->NetDiskPort = NDAS_DEVICE_LPX_PORT;
	pUsageReply->UnitDiskNo = unitDeviceId.UnitNo;
	pUsageReply->UsageID = 0;
	pUsageReply->SWMajorVersion = NDASIX_VERSION_MAJOR;
	pUsageReply->SWMinorVersion = NDASIX_VERSION_MINOR;
	pUsageReply->SWBuildNumber = NDASIX_VERSION_BUILD;
	pUsageReply->NDFSCompatVersion = m_NDFSVersion.wMajor;
	pUsageReply->NDFSVersion = m_NDFSVersion.wMinor;

	DWORD cbSent = 0;
	fSuccess = sock.SendToSync(pRemoteAddr, cbPacket, pbPacket, 0, &cbSent);
	if (!fSuccess) {
		DBGPRT_ERR_EX(_FT("Failed to send a reply (%d bytes): "), cbPacket);
		return;
	}

	return;
}
Пример #11
0
DWORD
CNdasService::OnServiceStop()
{
	//
	// We should report the SCM that the service is stopping
	// Otherwise, the service will terminate the thread.
	// And we'll get ACCESS VIOLATION ERROR!
	//

	DBGPRT_INFO(_FT("Service is stopping...\n"));

#if 0
	//
	// Eject all logical device instances
	//
	if (NULL != GetTaskHandle()) {
		CNdasInstanceManager* pInstMan = CNdasInstanceManager::Instance();
		if (NULL != pInstMan) {
			CNdasLogicalDeviceManager* pLdm = pInstMan->GetLogDevMan();
			if (NULL != pLdm) {
				pLdm->Lock();
				CNdasLogicalDeviceManager::ConstIterator itr =
					pLdm->begin();
				for (; itr != pLdm->end(); ++itr) {
					CNdasLogicalDevice* pLogDevice = itr->second;
					if (NDAS_LOGICALDEVICE_STATUS_MOUNTED == pLogDevice->GetStatus()) {
						//
						// If we should call pLogDevice->Eject here,
						// we must wait here until eject is really complete.
						//
						BOOL fSuccess = pLogDevice->Eject();
						ReportStatusToSCMgr(SERVICE_STOP_PENDING, 3000);
						::Sleep(2000);
					}
				}
				pLdm->Unlock();
			}
		}
	}
#endif

	ReportStatusToSCMgr(SERVICE_STOP_PENDING, 3000);

	HANDLE hTask = GetTaskHandle();
	this->Stop(FALSE);
	
	DWORD dwWaitTimeout = 3000L; // 3 sec
	ReportStatusToSCMgr(SERVICE_STOP_PENDING, 3000);
	DWORD dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout);

	if (WAIT_OBJECT_0 == dwWaitResult) {
		ReportStatusToSCMgr(SERVICE_STOPPED, 1000, NO_ERROR);
		return NO_ERROR;
	}

	ReportStatusToSCMgr(SERVICE_STOP_PENDING);
	dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout);

	if (WAIT_OBJECT_0 == dwWaitResult) {
		ReportStatusToSCMgr(SERVICE_STOPPED, 1000, NO_ERROR);
		return NO_ERROR;
	}

	ReportStatusToSCMgr(SERVICE_STOP_PENDING);
	dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout);

	if (WAIT_OBJECT_0 == dwWaitResult) {
		ReportStatusToSCMgr(SERVICE_STOPPED, 1000, NO_ERROR);
		return NO_ERROR;
	}

	ReportStatusToSCMgr(SERVICE_STOP_PENDING);
	dwWaitResult = ::WaitForSingleObject(hTask, dwWaitTimeout);

	if (dwWaitResult == WAIT_TIMEOUT) {
	}

	ReportStatusToSCMgr(SERVICE_STOPPED, 100, 1);
	return 1;
}