Пример #1
0
BOOL
WINAPI
NdasDmGetDiskNumbersOfVolume(
    HANDLE hVolume,
    LPDWORD pDiskNumbers,
    DWORD dwDiskNumbers,
    LPDWORD lpdwDiskNumbersUsed)
{
    BOOL fSuccess(FALSE);
    DWORD cbReturned(0);

    //
    // Prepare Volume Disk Extent Buffer
    //
    DWORD cbVolumeDiskExtents = sizeof(VOLUME_DISK_EXTENTS) +
                                MAX_VOL_DISK_EXTS * sizeof(VOLUME_DISK_EXTENTS);

    PVOLUME_DISK_EXTENTS pVolumeDiskExtents =
        (PVOLUME_DISK_EXTENTS) ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbVolumeDiskExtents);

    if (NULL == pVolumeDiskExtents) {
        DPErrorEx(_FT("Memory allication (%d bytes) failed: "), cbVolumeDiskExtents);
        return FALSE;
    }

    //
    // Get Volume Disk Extents
    //

    DPTrace(_FT("DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS)\n"));

    fSuccess = ::DeviceIoControl(
                   hVolume,
                   IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
                   NULL,
                   0,
                   pVolumeDiskExtents,
                   cbVolumeDiskExtents,
                   &cbReturned,
                   NULL);

    if (!fSuccess) {
        DPErrorEx(_FT("DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS) failed: "));
        ::HeapFree(::GetProcessHeap(), 0, pVolumeDiskExtents);
        return FALSE;
    }

    //
    //	usually it returns one disk device
    //
    *lpdwDiskNumbersUsed = 0;
    for (DWORD i = 0; i < pVolumeDiskExtents->NumberOfDiskExtents; ++i) {
        DPInfo(_FT("Extents[%d]:: Disk Number: %d, Starting Offset: %d, Extent Length: %d.\n"),
               i,
               pVolumeDiskExtents->Extents[i].DiskNumber,
               pVolumeDiskExtents->Extents[i].StartingOffset,
               pVolumeDiskExtents->Extents[i].ExtentLength);

        if (i < dwDiskNumbers) {
            pDiskNumbers[i] = pVolumeDiskExtents->Extents[i].DiskNumber;
            ++(*lpdwDiskNumbersUsed);
        }
    }

    ::HeapFree(::GetProcessHeap(), 0, pVolumeDiskExtents);
    return TRUE;
}
Пример #2
0
int drvinst(int argc, LPTSTR *argv)
{
	typedef enum { SVC_INSTALL, SVC_REMOVE, SVC_REMOVE_PNP } COMMAND_TYPE;

	struct { COMMAND_TYPE type; LPCTSTR cmd; int argc; BOOL op; } opts[] = 
	{ 
		{ SVC_INSTALL, L"install", 3, TRUE}, 
		{ SVC_REMOVE, L"remove", 1, FALSE},
		{ SVC_REMOVE_PNP, L"removepnp", 1, FALSE}
	};

	COMMAND_TYPE CmdType;

	const DWORD nopts = RTL_NUMBER_OF(opts);
	DWORD i = 0;

	for (; i < nopts; ++i) {
		if (lstrcmpi(opts[i].cmd, argv[0]) == 0) {
			if ((argc - 1) == opts[i].argc ||
				(opts[i].op && (argc - 1) >= opts[i].argc)) 
			{
				CmdType = opts[i].type;
			} else {
				_ftprintf(stderr, _T("Invalid command arguments.\n"));
				return 254;
			}
			break;
		}
	}

	if (i == nopts) {
		_ftprintf(stderr, _T("Invalid command.\n"));
		return 254;
	}

	if (SVC_INSTALL == CmdType) {

		LPTSTR szSourceFilePath = argv[1];
		LPTSTR szServiceName = argv[2];
		LPTSTR szDisplayName = argv[3];

		LPTSTR szLoadOrderGroup = NULL;
		if (argc > 4) {
			szLoadOrderGroup = argv[4];
		}

		DPInfo(_FT("Source: %s, ServiceName: %s, DisplayName: %s, LoadOrder: %s"),
			szSourceFilePath, szServiceName, szDisplayName, szLoadOrderGroup);

		BOOL bUpdated;
		BOOL fSuccess = NdasDiInstallOrUpdateDriverService(
			szSourceFilePath,
			szServiceName,
			szDisplayName,
			_T(""),
			SERVICE_KERNEL_DRIVER,
			SERVICE_SYSTEM_START,
			SERVICE_ERROR_NORMAL,
			szLoadOrderGroup,
			NULL,
			NULL,
			&bUpdated);

		if (!fSuccess) {
			printErrorText();
			return 254;
		} else {
			if (bUpdated)
			{
				_ftprintf(stdout, 
					_T("Driver Service %s updated successfully.\n"), szServiceName);
			}
			else
			{
				_ftprintf(stdout, 
					_T("Driver Service %s installed successfully.\n"), szServiceName);
			}
			return 0;
		}

	} else if (SVC_REMOVE == CmdType) {

		LPTSTR szServiceName = argv[1];

		BOOL fSuccess = NdasDiDeleteService(szServiceName);

		if (!fSuccess) {
			printErrorText();
			return 254;
		} else {
			_ftprintf(stdout, 
				_T("Driver Service %s deleted successfully.\n"), szServiceName);
		}

	} else if (SVC_REMOVE_PNP == CmdType) {

		LPTSTR szServiceName = argv[1];

		DWORD cRemoved;
		BOOL fRebootRequired;
		BOOL fSuccess = NdasDiRemoveLegacyDevice(
			NULL,
			szServiceName,
			FALSE,
			&cRemoved,
			&fRebootRequired,
			NULL,
			NULL);

		if (!fSuccess) {
			printErrorText();
			return 254;
		}

		_ftprintf(stdout,
			_T("Driver Enum Key (%d) removed successfully.%s\n"),
			cRemoved,
			fRebootRequired ? _T(" (Reboot required)") : _T(""));

	} else {

		_ftprintf(stderr, _T("Unknown command.\n"));
		return 254;

	}

	return 0;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
BOOL CNamedPipeTransport::Send(
	LPCVOID lpBuffer, DWORD cbToSend, LPDWORD lpcbSent, 
	LPOVERLAPPED lpOverlapped, DWORD dwFlags)
{
//	AUTOFUNCTRACE();

	_ASSERTE(!IsBadReadPtr(lpBuffer, cbToSend));
	_ASSERTE(!IsBadWritePtr(lpcbSent, sizeof(DWORD)));
	_ASSERTE(
		(NULL == lpOverlapped) || 
		(!IsBadReadPtr(lpOverlapped, sizeof(OVERLAPPED)) &&
		NULL != lpOverlapped->hEvent &&
		INVALID_HANDLE_VALUE != lpOverlapped->hEvent));

	UNREFERENCED_PARAMETER(dwFlags);

	// handling sending zero-byte packet
	if (cbToSend == 0) {
		*lpcbSent = 0;
		if (lpOverlapped) {
			BOOL fSuccess = ::SetEvent(lpOverlapped->hEvent);
			_ASSERT(fSuccess);
		}
		DPInfo(_FT("Sending 0 byte ignored\n"));
		return TRUE;
	}

	DPInfo(_FT("Sending %d bytes.\n"), cbToSend);

	BOOL fSuccess(FALSE);
	DWORD cbCurSent(0), cbCurToSend(cbToSend);
	const BYTE* lpCurBuffer = reinterpret_cast<const BYTE*>(lpBuffer);
	*lpcbSent = 0;

	while (cbCurToSend > 0) {

		fSuccess = ::WriteFile(m_hPipe, lpBuffer, cbCurToSend, &cbCurSent, lpOverlapped);
		if (!fSuccess && NULL != lpOverlapped && ::GetLastError() != ERROR_IO_PENDING) {
			break;
		}

		if (lpOverlapped) {
			// wait until timeout (to prevent indefinite waiting...)
			DWORD dwWaitResult = ::WaitForSingleObject(lpOverlapped->hEvent, TRANSMIT_TIMEOUT);
			if (dwWaitResult != WAIT_OBJECT_0) {
				switch (dwWaitResult) {
				case WAIT_TIMEOUT:		::SetLastError(WAIT_TIMEOUT);
				case WAIT_ABANDONED:	::SetLastError(WAIT_ABANDONED);
				default:	break;
				}
				return FALSE;
			}
			fSuccess = ::GetOverlappedResult(m_hPipe, lpOverlapped, &cbCurSent, TRUE);
			if (!fSuccess && ::GetLastError() != ERROR_IO_PENDING) {
				break;
			}
		}

		cbCurToSend -= cbCurSent;
		*lpcbSent += cbCurSent;
		lpCurBuffer += cbCurSent;

	}

	DPInfo(_FT("Sent %d bytes.\n"), *lpcbSent);

	return fSuccess;
}
Пример #8
0
BOOL CNamedPipeTransport::Receive(
	LPVOID lpBuffer, DWORD cbToReceive, LPDWORD lpcbReceived,
	LPOVERLAPPED lpOverlapped, LPDWORD lpdwFlags)
{
	// AUTOFUNCTRACE();

	_ASSERTE(!IsBadWritePtr(lpBuffer, cbToReceive));
	_ASSERTE(!IsBadWritePtr(lpcbReceived, sizeof(DWORD)));
	_ASSERTE(NULL == lpOverlapped ||
		!IsBadWritePtr(lpOverlapped, sizeof(OVERLAPPED)) &&
		NULL != lpOverlapped->hEvent &&
		INVALID_HANDLE_VALUE != lpOverlapped->hEvent);
		
	UNREFERENCED_PARAMETER(lpdwFlags);

	// handling sending zero-byte packet
	if (cbToReceive == 0) {
		*lpcbReceived = 0;
		if (lpOverlapped) {
			BOOL fSuccess = ::SetEvent(lpOverlapped->hEvent);
			_ASSERT(fSuccess);
		}
		return TRUE;
	}

	// we have to receive by the request size

	DPInfo(_FT("Reading %d bytes.\n"), cbToReceive);

	BOOL fSuccess(FALSE);
	DWORD cbCurReceived(0), cbCurToReceive(cbToReceive);
	LPBYTE lpCurBuffer = reinterpret_cast<LPBYTE>(lpBuffer);
	*lpcbReceived = 0;

	while (cbCurToReceive > 0) {

		fSuccess = ::ReadFile(m_hPipe, lpBuffer, cbCurToReceive, &cbCurReceived, lpOverlapped);
		if (!fSuccess && NULL != lpOverlapped && ::GetLastError() != ERROR_IO_PENDING) {
			break;
		}

		if (lpOverlapped) {
			// wait until timeout (to prevent indefinite waiting...)
			DWORD dwWaitResult = ::WaitForSingleObject(lpOverlapped->hEvent, TRANSMIT_TIMEOUT);
			if (dwWaitResult != WAIT_OBJECT_0) {
				switch (dwWaitResult) {
				case WAIT_TIMEOUT:		::SetLastError(WAIT_TIMEOUT);
				case WAIT_ABANDONED:	::SetLastError(WAIT_ABANDONED);
				default:	break;
				}
				return FALSE;
			}
			fSuccess = ::GetOverlappedResult(m_hPipe, lpOverlapped, &cbCurReceived, TRUE);
			if (!fSuccess && ::GetLastError() != ERROR_IO_PENDING) {
				break;
			}
		}

		cbCurToReceive -= cbCurReceived;
		*lpcbReceived += cbCurReceived;
		lpCurBuffer += cbCurReceived;

	}

	DPInfo(_FT("Read %d bytes.\n"), *lpcbReceived);

	return fSuccess;
}