Example #1
0
BOOL
WINAPI
NdasDmGetNdasLogDevSlotNoOfDisk(HANDLE hDisk, LPDWORD lpdwSlotNo)
{
    _ASSERTE(INVALID_HANDLE_VALUE != hDisk);
    _ASSERTE(NULL != hDisk);
    _ASSERTE(!IsBadWritePtr(lpdwSlotNo, sizeof(DWORD)));

    BOOL fSuccess(FALSE);
    DWORD dwScsiPortNumber;
    fSuccess = NdasDmGetScsiPortNumberOfDisk(hDisk, &dwScsiPortNumber);
    if (!fSuccess) {
        DPError(_FT("NdasDmGetScsiPortNumberOfDisk(%p) failed.\n"),
                hDisk);
        return FALSE;
    }

    fSuccess = NdasDmGetNdasLogDevSlotNoOfScsiPort(dwScsiPortNumber, lpdwSlotNo);
    if (!fSuccess) {
        DPError(_FT("NdasDmGetNdasLogDevSlotNoOfScsiPort(%d) failed.\n"),
                dwScsiPortNumber);
        return FALSE;
    }

    return TRUE;
}
Example #2
0
BOOL
CNdasDeviceComm::GetDiskInfoBlock(PNDAS_DIB pDiskInfoBlock)
{
	_ASSERTE(m_bInitialized && "CNdasDeviceComm is not initialized");
	_ASSERTE(pDiskInfoBlock != NULL);

	//
	// Read Last Sector for NDAS_UNITDISK_INFORMATION_BLOCK
	//
	unsigned _int8 ui8IdeResponse;

	PTARGET_DATA pTargetData = &m_lspath.PerTarget[m_dwUnitNo];
	UINT64 ui64DiskBlock = pTargetData->SectorCount - 1;

	INT iResult = IdeCommand(
		&m_lspath, m_dwUnitNo, 0, 
		WIN_READ, 
		ui64DiskBlock, 1, 0,
		(PCHAR) pDiskInfoBlock, &ui8IdeResponse);

	if (0 != iResult) {
		DPError(_FT("IdeCommand failed with error %d, ide response %d.\n"), iResult, ui8IdeResponse);
		return FALSE;
	}

	return TRUE;
}
Example #3
0
BOOL
WINAPI
NdasDmGetScsiPortNumberOfDisk(
    IN DWORD dwPhysicalDiskNumber,
    OUT LPDWORD lpdwScsiPortNumber)
{
    _ASSERTE(!IsBadWritePtr(lpdwScsiPortNumber, sizeof(DWORD)));

    //
    //	make up Physical Drive Name
    //

    TCHAR szDiskDevicePath[_MAX_PATH + 1];

    HRESULT hr = ::StringCchPrintf(
                     szDiskDevicePath,
                     _MAX_PATH + 1,
                     _T("\\\\.\\PHYSICALDRIVE%d"),
                     dwPhysicalDiskNumber);

    _ASSERT(SUCCEEDED(hr));

    DPInfo(_FT("Disk Device Path:%s\n"), szDiskDevicePath);

    //
    //	open the disk device
    //

    DPTrace(_FT("CreateFile(%s)\n"), szDiskDevicePath);

    HANDLE hDisk = ::CreateFile(
                       szDiskDevicePath,
                       GENERIC_READ |  GENERIC_WRITE,
                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);

    if (INVALID_HANDLE_VALUE == hDisk) {
        DPErrorEx(_FT("CreateFile(%s) failed: "), szDiskDevicePath);
        return FALSE;
    }

    //
    // Get SCSI Port Number of the Disk
    //

    BOOL fSuccess = NdasDmGetScsiPortNumberOfDisk(hDisk, lpdwScsiPortNumber);
    if (!fSuccess) {
        DPError(_FT("NdasDmGetScsiPortNumberOfDisk(%s) failed.\n"),
                szDiskDevicePath);
        (VOID) ::CloseHandle(hDisk);
        return FALSE;
    }

    (VOID) ::CloseHandle(hDisk);
    return TRUE;
}
Example #4
0
BOOL
CNdasDeviceComm::ReadDiskBlock(PBYTE pBlockBuffer, INT64 i64DiskBlock, INT32 i32BlockSize)
{
	_ASSERTE(m_bInitialized && "CNdasDeviceComm is not initialized");
	_ASSERTE(pBlockBuffer != NULL);
	_ASSERTE(i32BlockSize >= 1 && i32BlockSize <= 128);
	_ASSERTE(!::IsBadWritePtr(pBlockBuffer, i32BlockSize * 512));

	//
	// Read Last Sector for NDAS_UNITDISK_INFORMATION_BLOCK
	//
	UINT8 ui8IdeResponse;

	PTARGET_DATA pTargetData = &m_lspath.PerTarget[m_dwUnitNo];

	INT64 i64AbsoluteBlock = (i64DiskBlock >= 0) ? 
		i64DiskBlock : 
		(INT64)pTargetData->SectorCount + i64DiskBlock;

	INT iResult = IdeCommand(
		&m_lspath, 
		m_dwUnitNo, 
		0, 
		WIN_READ, 
		i64AbsoluteBlock, 
		(INT16)i32BlockSize, 
		0,
		(PCHAR) pBlockBuffer, &ui8IdeResponse);

	if (0 != iResult) {
		DPError(_FT("IdeCommand failed with error %d, ide response %d.\n"), iResult, ui8IdeResponse);
		return FALSE;
	}

	return TRUE;
}
Example #5
0
BOOL
WINAPI
NdasDmGetNdasLogDevSlotNoOfScsiPort(
    HANDLE hScsiPort,
    LPDWORD lpdwSlotNo)
{
    //
    // Make up IOCTL In-parameter
    // LANSCSIMINIPORT_IOCTL_GET_SLOT_NO to get Logical Device Slot No
    //

    BOOL fSuccess(FALSE);

    const DWORD cbHeader = sizeof(SRB_IO_CONTROL);
    const DWORD cbData = sizeof(ULONG);
    const DWORD cbInBuffer = cbHeader + cbData;
    DWORD cbReturned(0);

    BYTE lpInBuffer[cbInBuffer];
    ::ZeroMemory(lpInBuffer, cbInBuffer);
    PSRB_IO_CONTROL pSrbIoControl = (PSRB_IO_CONTROL) lpInBuffer;

    pSrbIoControl->HeaderLength = cbHeader;
    ::CopyMemory(pSrbIoControl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE, 8);
    pSrbIoControl->Timeout = 10;
    pSrbIoControl->ControlCode = LANSCSIMINIPORT_IOCTL_GET_SLOT_NO;
    pSrbIoControl->Length = cbData;

    //
    // Get Logical Device Slot No
    //

    fSuccess = ::DeviceIoControl(
                   hScsiPort,
                   IOCTL_SCSI_MINIPORT,
                   lpInBuffer,
                   cbInBuffer,
                   lpInBuffer, // we use the same buffer for output
                   cbInBuffer,
                   &cbReturned,
                   NULL);

    if (!fSuccess) {
        DPErrorEx(_FT("DeviceIoControl(IOCTL_SCSI_MINIPORT,")
                  _T("LANSCSIMINIPORT_IOCTL_GET_SLOT_NO) failed: "));
        return FALSE;
    }

    if (0 != pSrbIoControl->ReturnCode) {
        DPError(_FT("DeviceIoControl(IOCTL_SCSI_MINIPORT,")
                _T("LANSCSIMINIPORT_IOCTL_GET_SLOT_NO) returned SrbIoControl error %d.\n"),
                pSrbIoControl->ReturnCode);
        ::SetLastError(NDASDM_ERROR_SRB_IO_CONTROL_ERROR);
        return FALSE;
    }

    //
    // Calculate the slot number offset and retrieve the value
    //

    ULONG* lpdwSlotNoOut = (ULONG*)(lpInBuffer + cbHeader);
    *lpdwSlotNo = *lpdwSlotNoOut;

    DPInfo(_FT("NDAS Logical Device Slot: %d\n"), *lpdwSlotNo);

    return TRUE;
}
Example #6
0
BOOL
WINAPI
NdasDmGetNdasLogDevSlotNoOfScsiPort(
    LPCWSTR wszDbccName, LPDWORD lpdwSlotNo)
{
    _ASSERTE(!IsBadWritePtr(lpdwSlotNo, sizeof(DWORD)));
    _ASSERTE(!IsBadStringPtr(wszDbccName, _MAX_PATH));

    DPInfo(_FT("NdasDmGetNdasLogDevSlotNoOfScsiPort got %s.\n"), wszDbccName);

    //
    // extract the last string between '&' and '#', which has slot number and unitdisk numer
    //
    // example of dbcc_name at logical device slot no 10
    //
    // \\?\lanscsibus#netdisk_v0#1&1a590e2c&5&10#{2accfe60-c130-11d2-b082-00a0c91efb8b}
    //                                       ^^^^

    if (!NdasDmIsLANSCSIPortInterface(wszDbccName)) {
        DPInfo(_FT("Non-LANSCSI Port Interface Name.\n"));
        return FALSE;
    }

    // skip LANSCSIIDDEV_IFDW
    LPCWSTR pwszLeftBound = &wszDbccName[LANSCSI_DEV_IFIDW_LEN];

    // pwszLeftBound now points to
    // \\?\lanscsibus#netdisk_v0#1&1a590e2c&5&10#{2accfe60-c130-11d2-b082-00a0c91efb8b}
    //                ^
    //                left bound

    while (*pwszLeftBound != L'#') {
        if (*pwszLeftBound == L'\0') {
            DPError(_FT("Slot Number Parse Error at left bound!\n"));
            return FALSE; // invalid!
        }
        ++pwszLeftBound;
    }

    // pwszpwszLeftBound now points to
    // \\?\lanscsibus#netdisk_v0#1&1a590e2c&5&10#{2accfe60-c130-11d2-b082-00a0c91efb8b}
    //                          ^
    //                      left bound

    LPCWSTR pwszRightBound = pwszLeftBound + 1;
    while (*pwszRightBound != L'#') {
        if (*pwszRightBound == L'\0') {
            DPError(_FT("Slot Number Parse Error at right bound!\n"));
            return FALSE; // invalid!
        }
        ++pwszRightBound;
    }

    // pwszRightBound now points to
    // \\?\lanscsibus#netdisk_v0#1&1a590e2c&5&10#{2accfe60-c130-11d2-b082-00a0c91efb8b}
    //                          ^               ^
    //                      left bound     right bound

    LPCWSTR pwszSlotStart = pwszRightBound - 1;
    while (*pwszSlotStart != L'&') {
        if (pwszSlotStart <= pwszLeftBound) {
            DPError(_FT("Slot Number Parse Error at slot start bound!\n"));
            return FALSE;
        }
        --pwszSlotStart;
    }

    // pwszRightBound now points to
    // \\?\lanscsibus#netdisk_v0#1&1a590e2c&5&10#{2accfe60-c130-11d2-b082-00a0c91efb8b}
    //                          ^            ^  ^
    //                      left bound       |  right bound
    //                                      slot start

    if (pwszSlotStart + 1 == pwszRightBound) {
        // &# -> no slot number
        DPError(_FT("Slot Number Parse Error at slot start bound!\n"));
        return FALSE;
    }

    WCHAR szSlotNo[10];
    LPCWSTR pch = pwszSlotStart + 1;
    DWORD i(0);
    for (; pch < pwszRightBound && i < 9; ++i, ++pch) {
        szSlotNo[i] = *pch;
    }
    szSlotNo[i] = L'\0';

    DWORD dwSlotNo = _wtoi(szSlotNo);
    if (dwSlotNo == 0) {
        DPError(_FT("Invalid slot number (%s) -> (%d)\n"), szSlotNo, dwSlotNo);
        return FALSE;
    }

    *lpdwSlotNo = dwSlotNo;

    DPInfo(_FT("Slot no is %d.\n"), dwSlotNo);
    return TRUE;

}
Example #7
0
BOOL
WINAPI
NdasDmGetNdasLogDevSlotNoOfVolume(
    HANDLE hVolume,
    LPDWORD lpdwSlotNo,
    DWORD nBuffer,
    LPDWORD lpdwBufferUsed)
{
    _ASSERTE(INVALID_HANDLE_VALUE != hVolume);
    _ASSERTE(NULL != hVolume);
    _ASSERTE(!IsBadWritePtr(lpdwSlotNo, sizeof(DWORD) * nBuffer));
    _ASSERTE(!IsBadWritePtr(lpdwBufferUsed, sizeof(DWORD)));

    BOOL fSuccess(FALSE);
    //
    // Get the physical disk numbers of the volume
    //
    DWORD pDiskNumbers[256];
    DWORD nDiskNumbers;

    fSuccess = NdasDmGetDiskNumbersOfVolume(hVolume, pDiskNumbers, 256, &nDiskNumbers);
    if (!fSuccess) {
        DPError(_FT("NdasDmGetDiskNumbersOfVolume failed.\n"));
        return FALSE;
    }

    //
    // Get SCSI port number for each disks
    //
    // TODO: Resolve this problem!
    // What if the volume is spanned through NDAS Logical Disks and
    // OS's regular Disks?
    //

    *lpdwBufferUsed = 0;
    for (DWORD i = 0; i < nDiskNumbers; ++i) {

        if (*lpdwBufferUsed >= nBuffer) {
            DPError(_FT("Insufficient Slot Buffer.\n"));
            ::SetLastError(ERROR_INSUFFICIENT_BUFFER);
            return FALSE;
        }

        DWORD dwDiskNumber = pDiskNumbers[i];
        DWORD dwScsiPortNumber;

        fSuccess = NdasDmGetScsiPortNumberOfDisk(dwDiskNumber, &dwScsiPortNumber);
        if (!fSuccess) {
            DPErrorEx(_FT("NdasDmGetScsiPortNumberOfDisk(%d) failed: "), dwDiskNumber);
            return FALSE;
        }

        DWORD dwSlotNo;
        fSuccess = NdasDmGetNdasLogDevSlotNoOfScsiPort(dwScsiPortNumber, &dwSlotNo);
        if (!fSuccess) {
            DPErrorEx(_FT("NdasDmGetNdasLogDevSlotNoOfScsiPort(%d) failed: "), dwScsiPortNumber);
            return FALSE;
        }

        BOOL bDuplicate(FALSE);
        for (DWORD j = 0; j < *lpdwBufferUsed; ++j) {
            if (lpdwSlotNo[j] == dwSlotNo) {
                bDuplicate = TRUE;
                break;
            }
        }

        if (!bDuplicate) {
            lpdwSlotNo[*lpdwBufferUsed] = dwSlotNo;
            (*lpdwBufferUsed)++;
        }

    }

    return TRUE;
}
Example #8
0
BOOL
WINAPI
NdasDmGetNdasLogDevSlotNoOfScsiPort(
    DWORD dwScsiPortNumber,
    LPDWORD lpdwSlotNo)
{
    BOOL fSuccess(FALSE);

    //
    // Make up SCSI Port Name
    //

    TCHAR szScsiPortName[_MAX_PATH + 1];
    HRESULT hr = ::StringCchPrintf(
                     szScsiPortName, _MAX_PATH + 1,
                     TEXT("\\\\.\\Scsi%d:"), dwScsiPortNumber);

    DPInfo(_FT("SCSI Port Name: %s\n"), szScsiPortName);

    //
    // Open SCSI Port Device
    //

    HANDLE hScsiPort = ::CreateFile(
                           szScsiPortName,
                           GENERIC_READ | GENERIC_WRITE,
                           FILE_SHARE_READ | FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

    if (INVALID_HANDLE_VALUE == hScsiPort) {
        DPErrorEx(_FT("CreateFile(%s) failed: "), szScsiPortName);
        return FALSE;
    }

    //
    // Make up IOCTL In-parameter
    // LANSCSIMINIPORT_IOCTL_GET_SLOT_NO to get Logical Device Slot No
    //

    const DWORD cbHeader = sizeof(SRB_IO_CONTROL);
    const DWORD cbData = sizeof(ULONG);
    const DWORD cbInBuffer = cbHeader + cbData;
    DWORD cbReturned(0);

    BYTE lpInBuffer[cbInBuffer];
    ::ZeroMemory(lpInBuffer, cbInBuffer);
    PSRB_IO_CONTROL pSrbIoControl = (PSRB_IO_CONTROL) lpInBuffer;

    pSrbIoControl->HeaderLength = cbHeader;
    ::CopyMemory(pSrbIoControl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE, 8);
    pSrbIoControl->Timeout = 10;
    pSrbIoControl->ControlCode = LANSCSIMINIPORT_IOCTL_GET_SLOT_NO;
    pSrbIoControl->Length = cbData;

    //
    // Get Logical Device Slot No
    //

    fSuccess = ::DeviceIoControl(
                   hScsiPort,
                   IOCTL_SCSI_MINIPORT,
                   lpInBuffer,
                   cbInBuffer,
                   lpInBuffer, // we use the same buffer for output
                   cbInBuffer,
                   &cbReturned,
                   NULL);

    if (!fSuccess) {
        DPErrorEx(_FT("DeviceIoControl(IOCTL_SCSI_MINIPORT,")
                  _T("LANSCSIMINIPORT_IOCTL_GET_SLOT_NO) failed: "));
        ::CloseHandle(hScsiPort);
        return FALSE;
    }

    if (0 != pSrbIoControl->ReturnCode) {
        DPError(_FT("DeviceIoControl(IOCTL_SCSI_MINIPORT,")
                _T("LANSCSIMINIPORT_IOCTL_GET_SLOT_NO) returned error %d.\n"),
                pSrbIoControl->ReturnCode);
        ::CloseHandle(hScsiPort);
        return FALSE;
    }

    //
    // Calculate the slot number offset and retrieve the value
    //

    ULONG* lpdwSlotNoOut = (ULONG*)(lpInBuffer + cbHeader);
    *lpdwSlotNo = *lpdwSlotNoOut;

    DPInfo(_FT("NDAS Logical Device Slot: %d\n"), *lpdwSlotNo);

    ::CloseHandle(hScsiPort);
    return TRUE;
}
Example #9
0
BOOL 
CNdasDeviceComm::GetUnitDeviceInformation(PNDAS_UNITDEVICE_INFORMATION pUnitDevInfo)
{
	_ASSERTE(m_bInitialized && "CNdasDeviceComm is not initialized");
	_ASSERTE(pUnitDevInfo != NULL);

	INT iResult = GetDiskInfo(&m_lspath, m_dwUnitNo);
	if (0 != iResult) {
		// TODO: LANDISK_ERROR_BADKEY?
		DPError(_FT("GetDiskInfo failed with error %d\n"), iResult);
		return FALSE;
	}

	PTARGET_DATA pTargetData = &m_lspath.PerTarget[m_dwUnitNo];

	pUnitDevInfo->bLBA = pTargetData->bLBA;
	pUnitDevInfo->bLBA48 = pTargetData->bLBA48;
	pUnitDevInfo->bPIO = pTargetData->bPIO;
	pUnitDevInfo->bDMA = pTargetData->bDma;
	pUnitDevInfo->bUDMA = pTargetData->bUDma;
	pUnitDevInfo->MediaType = pTargetData->MediaType;

	pUnitDevInfo->dwROHosts = pTargetData->NRROHost;
	pUnitDevInfo->dwRWHosts = pTargetData->NRRWHost;
	pUnitDevInfo->SectorCount = pTargetData->SectorCount;

#ifdef UNICODE

	//
	// What if FwRev, Model, SerialNo is not null terminated?
	// -> solved by terminating null between fields

	_ASSERTE(sizeof(pUnitDevInfo->szModel) / sizeof(pUnitDevInfo->szModel[0]) == sizeof(pTargetData->Model));
	_ASSERTE(sizeof(pUnitDevInfo->szSerialNo) / sizeof(pUnitDevInfo->szSerialNo[0]) == sizeof(pTargetData->SerialNo));
	_ASSERTE(sizeof(pUnitDevInfo->szFwRev) / sizeof(pUnitDevInfo->szFwRev[0]) == sizeof(pTargetData->FwRev));

	::MultiByteToWideChar(
		CP_ACP, 0, 
		pTargetData->Model, sizeof(pTargetData->Model), 
		pUnitDevInfo->szModel, sizeof(pUnitDevInfo->szModel) / sizeof(pUnitDevInfo->szModel[0]));

	::MultiByteToWideChar(
		CP_ACP, 0, 
		pTargetData->SerialNo, sizeof(pTargetData->SerialNo), 
		pUnitDevInfo->szSerialNo, sizeof(pUnitDevInfo->szSerialNo) / sizeof(pUnitDevInfo->szSerialNo[0]));

	::MultiByteToWideChar(
		CP_ACP, 0, 
		pTargetData->FwRev, sizeof(pTargetData->FwRev), 
		pUnitDevInfo->szFwRev, sizeof(pUnitDevInfo->szFwRev) / sizeof(pUnitDevInfo->szFwRev[0]));

#else

	_ASSERTE(sizeof(pUnitDevInfo->szModel) == sizeof(pTargetData->Model));
	_ASSERTE(sizeof(pUnitDevInfo->szFwRev) == sizeof(pTargetData->FwRev));
	_ASSERTE(sizeof(pUnitDevInfo->szSerialNo) == sizeof(pTargetData->SerialNo));

	::CopyMemory(pUnitDevInfo->szModel, pTargetData->Model, sizeof(pTargetData->Model));
	::CopyMemory(pUnitDevInfo->szFwRev, pTargetData->FwRev, sizeof(pTargetData->FwRev));
	::CopyMemory(pUnitDevInfo->szSerialNo, pTargetData->SerialNo, sizeof(pTargetData->SerialNo));

#endif

	DPInfo(_FT("Model        : %s\n"), pUnitDevInfo->szModel);
	DPInfo(_FT("Serial No    : %s\n"), pUnitDevInfo->szSerialNo);
	DPInfo(_FT("Firmware Rev : %s\n"), pUnitDevInfo->szFwRev);

	return TRUE;
}
Example #10
0
static 
HANDLE 
CreatePipeConnection(LPOVERLAPPED lpOverlapped)
{
	HANDLE hPipe = ::CreateFile(
			NDAS_EVENT_PIPE_NAME,
			GENERIC_READ,
			FILE_SHARE_READ,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
			NULL);

	if (INVALID_HANDLE_VALUE == hPipe)
	{
		DPErrorEx(_FT("Connecting to %s failed: "), NDAS_EVENT_PIPE_NAME);
		return INVALID_HANDLE_VALUE;
	}

	//
	// We should read the event version info immediately
	//
	NDAS_EVENT_MESSAGE message = {0};
	DWORD cbMessage = sizeof(NDAS_EVENT_MESSAGE);
	DWORD cbRead(0);

	BOOL fSuccess = ::ReadFile(
		hPipe,
		&message,
		cbMessage,
		&cbRead,
		lpOverlapped);

	if (!fSuccess && ERROR_IO_PENDING != ::GetLastError()) {
		DPErrorEx(_FT("Retrieving version information failed on ReadFile: "));
		::CloseHandle(hPipe);
		return INVALID_HANDLE_VALUE;
	}

	if (fSuccess) {
		fSuccess = ::SetEvent(lpOverlapped->hEvent);
		_ASSERTE(fSuccess);
	}

	//
	// If we cannot retrieve the version information
	// in a timeout interval or the version information
	// is mismatch, an error is returned
	//

	const DWORD dwTimeout = 3000; // 3 sec timeout
	DWORD dwWaitResult = ::WaitForSingleObject(
		lpOverlapped->hEvent,
		dwTimeout);

	if (dwWaitResult == WAIT_TIMEOUT) {
		DPError(_FT("Retrieving version information timed out."));
		::CloseHandle(hPipe);
		return INVALID_HANDLE_VALUE;
	}

	if (dwWaitResult != WAIT_OBJECT_0) {
		DPErrorEx(_FT("Retrieving version information failed: "));
		::CloseHandle(hPipe);
		return INVALID_HANDLE_VALUE;
	}

	fSuccess = ::GetOverlappedResult(
		hPipe,
		lpOverlapped,
		&cbRead,
		TRUE);

	if (!fSuccess) {
		DPErrorEx(_FT("Getting overlapped result failed: "));
		::CloseHandle(hPipe);
		return INVALID_HANDLE_VALUE;
	}

	if (NDAS_EVENT_TYPE_VERSION_INFO != message.EventType) {
		DPError(_FT("Getting Event Version Info failed: ")
			_T("Type expected %d, received %d.\n"),
			NDAS_EVENT_TYPE_VERSION_INFO, message.EventType);
		::CloseHandle(hPipe);
		::SetLastError(NDASUSER_ERROR_EVENT_VERSION_MISMATCH);
		return INVALID_HANDLE_VALUE;
	}

	if (NDAS_EVENT_VERSION_MAJOR != message.VersionInfo.MajorVersion ||
		NDAS_EVENT_VERSION_MINOR != message.VersionInfo.MinorVersion)
	{
		DPErrorEx(_FT("Event version mismatch: ")
			_T("Version expected %d.%d, received %d.%d"),
			NDAS_EVENT_VERSION_MAJOR, NDAS_EVENT_VERSION_MINOR,
			message.VersionInfo.MajorVersion, message.VersionInfo.MinorVersion);
		::CloseHandle(hPipe);
		::SetLastError(NDASUSER_ERROR_EVENT_VERSION_MISMATCH);
		return INVALID_HANDLE_VALUE;
	}

	return hPipe;
}
Example #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;
}