Пример #1
0
static NTSTATUS EvhdRegisterIo(ParserInstance *parser, BOOLEAN flag1, BOOLEAN flag2, PGUID pSnapshotId)
{
	NTSTATUS status = STATUS_SUCCESS;

	if (!parser->bIoRegistered)
	{
		REGISTER_IO_REQUEST request = { 0 };
		REGISTER_IO_RESPONSE response = { 0 };
		SCSI_ADDRESS scsiAddressResponse = { 0 };

		request.dwVersion = 1;
		request.dwFlags = flag1 ? 9 : 8;
		if (flag2) request.wFlags |= 0x1;
        request.SnapshotId = *pSnapshotId;
		request.pfnCompleteScsiRequest = &EvhdCompleteScsiRequest;
		request.pfnSendMediaNotification = &EvhdSendMediaNotification;
		request.pfnSendNotification = &EvhdSendNotification;
		request.pVstorInterface = parser->pVstorInterface;
		request.wMountFlags = parser->wMountFlags;

        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_REGISTER_IO, &request, sizeof(REGISTER_IO_REQUEST),
            &response, sizeof(REGISTER_IO_RESPONSE));

		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "IOCTL_STORAGE_REGISTER_IO failed with error 0x%0X\n", status);
			return status;
		}

		parser->bIoRegistered = TRUE;
		parser->dwDiskSaveSize = response.dwDiskSaveSize;
        parser->dwInnerBufferSize = sizeof(PARSER_STATE) + response.dwExtensionBufferSize;
		parser->Io = response.Io;

		status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &scsiAddressResponse, sizeof(SCSI_ADDRESS));

		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "IOCTL_SCSI_GET_ADDRESS failed with error 0x%0X\n", status);
			return status;
		}

		parser->ScsiLun = scsiAddressResponse.Lun;
		parser->ScsiPathId = scsiAddressResponse.PathId;
		parser->ScsiTargetId = scsiAddressResponse.TargetId;
	}

	return status;
}
Пример #2
0
static NTSTATUS EvhdInitialize(HANDLE hFileHandle, PFILE_OBJECT pFileObject, ParserInstance *parser)
{
	NTSTATUS status = STATUS_SUCCESS;

	parser->pVhdmpFileObject = pFileObject;
	parser->FileHandle = hFileHandle;
	
	/* Initialize Direct IO */
	parser->pDirectIoIrp = IoAllocateIrp(IoGetRelatedDeviceObject(parser->pVhdmpFileObject)->StackSize, FALSE);
	if (!parser->pDirectIoIrp)
	{
        LOG_PARSER(LL_FATAL, "IoAllocateIrp failed\n");
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	
	/* Initialize QoS */
	parser->pQoSStatusIrp = IoAllocateIrp(IoGetRelatedDeviceObject(parser->pVhdmpFileObject)->StackSize, FALSE);
	if (!parser->pQoSStatusIrp)
	{
        LOG_PARSER(LL_FATAL, "IoAllocateIrp failed\n");
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	parser->pQoSStatusBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, QoSBufferSize, EvhdQoSPoolTag);
	if (!parser->pQoSStatusBuffer)
	{
        LOG_PARSER(LL_FATAL, "ExAllocatePoolWithTag failed\n");
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	/* Initialize CTL */
	ExInitializeRundownProtection(&parser->RecoveryRundownProtection);
	parser->pRecoveryStatusIrp = IoAllocateIrp(IoGetRelatedDeviceObject(parser->pVhdmpFileObject)->StackSize, FALSE);
	if (!parser->pRecoveryStatusIrp)
	{
        LOG_PARSER(LL_FATAL, "IoAllocateIrp failed\n");
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	parser->FileHandle = hFileHandle;
	parser->pVhdmpFileObject = pFileObject;

	return status;
}
Пример #3
0
NTSTATUS EVhdMountDisk(ParserInstance *parser, UCHAR flags, PGUID pUnkGuid, __out PARSER_MOUNT_INFO *mountInfo)
{
	NTSTATUS status = STATUS_SUCCESS;

	status = EvhdRegisterIo(parser, flags & 1, (flags >> 1) & 1, pUnkGuid);
	if (!NT_SUCCESS(status))
	{
        LOG_PARSER(LL_FATAL, "EvhdRegisterIo failed with error 0x%0x\n", status);
		EvhdUnregisterIo(parser);
		return status;
	}
	parser->bMounted = TRUE;
	mountInfo->dwInnerBufferSize = parser->dwInnerBufferSize;
	mountInfo->bUnk = FALSE;
	mountInfo->bFastPause = parser->bFastPause;
	mountInfo->bFastClose = parser->bFastClose;

	return status;
}
Пример #4
0
NTSTATUS EVhdQueryInformationDisk(ParserInstance *parser, EDiskInfoType type, INT unused1, INT unused2, PVOID pBuffer, INT *pBufferSize)
{
	NTSTATUS status = STATUS_SUCCESS;
    DISK_INFO_REQUEST Request = { EDiskInfoType_Geometry };
	DISK_INFO_RESPONSE Response = { 0 };

	UNREFERENCED_PARAMETER(unused1);
	UNREFERENCED_PARAMETER(unused2);

	if (EDiskInfo_Format == type)
	{
		ASSERT(0x38 == sizeof(DISK_INFO_FORMAT));
        if (*pBufferSize < sizeof(DISK_INFO_FORMAT))
			return status = STATUS_BUFFER_TOO_SMALL;
        DISK_INFO_FORMAT *pRes = pBuffer;
        memset(pBuffer, 0, sizeof(DISK_INFO_FORMAT));

		Request.RequestCode = EDiskInfoType_Type;
		status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve disk type. 0x%0X\n", status);
			return status;
		}
		pRes->DiskType = Response.vals[0].dwLow;

        Request.RequestCode = EDiskInfoType_ParserInfo;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve parser info. 0x%0X\n", status);
			return status;
		}
		pRes->DiskFormat = Response.vals[0].dwLow;

        Request.RequestCode = EDiskInfoType_Geometry;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve size info. 0x%0X\n", status);
			return status;
		}
		pRes->dwBlockSize = Response.vals[2].dwLow;
		pRes->qwDiskSize = Response.vals[1].qword;

        Request.RequestCode = EDiskInfoType_LinkageId;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve linkage identifier. 0x%0X\n", status);
			return status;
		}
		pRes->LinkageId = Response.guid;

        Request.RequestCode = EDiskInfoType_InUseFlag;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve in use flag. 0x%0X\n", status);
			return status;
		}
		pRes->bIsInUse = (BOOLEAN)Response.vals[0].dwLow;

        Request.RequestCode = EDiskInfoType_IsFullyAllocated;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve fully allocated flag. 0x%0X\n", status);
			return status;
		}
		pRes->bIsFullyAllocated = (BOOLEAN)Response.vals[0].dwLow;

        Request.RequestCode = EDiskInfoType_PhysicalDisk;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve unk9 flag. 0x%0X\n", status);
			return status;
		}
		pRes->IsRemote = (BOOLEAN)Response.vals[0].dwLow;

        Request.RequestCode = EDiskInfoType_Page83Data;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve disk identifier. 0x%0X\n", status);
			return status;
		}
		pRes->DiskIdentifier = Response.guid;

        *pBufferSize = sizeof(DISK_INFO_FORMAT);
	}
	else if (EDiskInfo_Fragmentation == type)
	{
		status = STATUS_INVALID_DEVICE_REQUEST;
	}
	else if (EDiskInfo_ParentNameList == type)
	{
#pragma pack(push, 1)
		typedef struct {
			ULONG64 f_0;
			UCHAR f_8;
			BOOLEAN bHaveParent;
			UCHAR _align[2];
			INT size;
			UCHAR data[1];
		} ParentNameResponse;

		typedef struct {
			UCHAR f_0;
			BOOLEAN bHaveParent;
			UCHAR _align[2];
			ULONG size;
			UCHAR data[1];
		} ResultBuffer;
#pragma pack(pop)
		if (*pBufferSize < 8)
			return status = STATUS_BUFFER_TOO_SMALL;
		ResultBuffer *pRes = (ResultBuffer *)pBuffer;
		memset(pRes, 0, 8);
		INT ResponseBufferSize = *pBufferSize + 0x18;
		ParentNameResponse *ResponseBuffer = (ParentNameResponse *)ExAllocatePoolWithTag(PagedPool, ResponseBufferSize, EvhdPoolTag);
		if (!ResponseBuffer)
			return STATUS_INSUFFICIENT_RESOURCES;
		Request.RequestCode = EDiskInfoType_ParentNameList;
		status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION, &Request, sizeof(Request),
			ResponseBuffer, ResponseBufferSize);
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve type info. 0x%0X\n", status);
			ExFreePoolWithTag(ResponseBuffer, EvhdPoolTag);
			return status;
		}
		pRes->f_0 = ResponseBuffer->f_8;
		pRes->bHaveParent = ResponseBuffer->bHaveParent;
		pRes->size = ResponseBuffer->size;
		if (ResponseBuffer->bHaveParent)
		{
			memmove(pRes->data, ResponseBuffer->data, pRes->size);
			ExFreePoolWithTag(ResponseBuffer, EvhdPoolTag);
			*pBufferSize = 8 + pRes->size;
		}
		else
			*pBufferSize = 8;
	}
	else if (EDiskInfo_PreloadDiskMetadata == type)
	{
		if (*pBufferSize < sizeof(BOOLEAN))
			return status = STATUS_BUFFER_TOO_SMALL;
		BOOLEAN *pRes = (BOOLEAN *)pBuffer;
		BOOLEAN Response = FALSE;
		status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_PRELOAD_DISK_METADATA_V2, NULL, 0,
			&Response, sizeof(BOOLEAN));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve type info. 0x%0X\n", status);
			return status;
		}
		*pRes = Response;
		*pBufferSize = sizeof(BOOLEAN);
	}
	else if (EDiskInfo_Geometry == type)
	{
		ASSERT(0x10 == sizeof(DISK_INFO_GEOMETRY));
        if (*pBufferSize < sizeof(DISK_INFO_GEOMETRY))
			return status = STATUS_BUFFER_TOO_SMALL;
        DISK_INFO_GEOMETRY *pRes = pBuffer;
        Request.RequestCode = EDiskInfoType_Geometry;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve size info. 0x%0X\n", status);
			return status;
		}
		pRes->dwSectorSize = Response.vals[2].dwHigh;
		pRes->qwDiskSize = Response.vals[0].qword;
        Request.RequestCode = EDiskInfoType_NumSectors;
        status = SynchronouseCall(parser->pVhdmpFileObject, IOCTL_STORAGE_VHD_GET_INFORMATION,
            &Request, sizeof(DISK_INFO_REQUEST), &Response, sizeof(DISK_INFO_RESPONSE));
		if (!NT_SUCCESS(status))
		{
            LOG_PARSER(LL_FATAL, "Failed to retrieve number of sectors. 0x%0X\n", status);
			return status;
		}
		pRes->dwNumSectors = Response.vals[0].dwLow;
        *pBufferSize = sizeof(DISK_INFO_GEOMETRY);
	}
	else
	{
        LOG_PARSER(LL_FATAL, "Unknown Disk info type %X\n", type);
		status = STATUS_INVALID_DEVICE_REQUEST;
	}

	return status;
}
Пример #5
0
NTSTATUS EVhdOpenDisk(PCUNICODE_STRING diskPath, ULONG32 OpenFlags, GUID *pVmId, PVOID vstorInterface, __out ParserInstance **ppOutParser)
{
	NTSTATUS status = STATUS_SUCCESS;
	PFILE_OBJECT pFileObject = NULL;
	HANDLE FileHandle = NULL;
	ParserInstance *parser = NULL;
	RESILIENCY_INFO_EA vmInfo = { 0 };

	if (pVmId)
	{
		vmInfo.NextEntryOffset = 0;
		vmInfo.EaValueLength = sizeof(GUID);
		vmInfo.EaNameLength = sizeof(vmInfo.EaName) - 1;
		strncpy(vmInfo.EaName, OPEN_FILE_RESILIENCY_INFO_EA_NAME, sizeof(vmInfo.EaName));
		vmInfo.EaValue = *pVmId;
	}
	status = OpenVhdmpDevice(&FileHandle, OpenFlags, &pFileObject, diskPath, pVmId ? &vmInfo : NULL);
	if (!NT_SUCCESS(status))
	{
        LOG_PARSER(LL_FATAL, "Failed to open vhdmp device for virtual disk file %S\n", diskPath->Buffer);
		goto failure_cleanup;
	}

	parser = (ParserInstance *)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(ParserInstance), EvhdPoolTag);
	if (!parser)
	{
        LOG_PARSER(LL_FATAL, "Failed to allocate memory for ParserInstance\n");
		status = STATUS_NO_MEMORY;
		goto failure_cleanup;
	}

	memset(parser, 0, sizeof(ParserInstance));

	status = EvhdInitialize(FileHandle, pFileObject, parser);

	if (!NT_SUCCESS(status))
		goto failure_cleanup;

	parser->wMountFlags = OpenFlags & 0x40 ? 4 : OpenFlags & 1;	// 4 - ignore SCSI_SYNCHRONIZE_CACHE opcodes, 1 - read only mount
	EvhdQueryBoolParameter(L"FastPause", TRUE, &parser->bFastPause);
	EvhdQueryBoolParameter(L"FastClose", TRUE, &parser->bFastClose);
	parser->pVstorInterface = vstorInterface;

	*ppOutParser = parser;

	goto cleanup;

failure_cleanup:
	if (FileHandle)
	{
		ZwClose(FileHandle);
		parser->FileHandle = NULL;
	}
	if (parser)
	{
		EVhdCloseDisk(parser);
	}

cleanup:
	return status;
}
Пример #6
0
char remote488_device::recv_update(uint8_t& data)
{
	char c;
	unsigned i;

	// Do not iterate too much..
	for (i = 0; i < 8 && m_stream->input(&c , 1); i++) {
		int prev_state = m_rx_state;
		switch (m_rx_state) {
		case REM_RX_WAIT_CH:
			if (is_msg_type(c)) {
				m_rx_ch = c;
				m_rx_state = REM_RX_WAIT_COLON;
			} else if (!is_space(c)) {
				m_rx_state = REM_RX_WAIT_WS;
			}
			break;

		case REM_RX_WAIT_COLON:
			if (c == ':') {
				m_rx_state = REM_RX_WAIT_1ST_HEX;
			} else {
				m_rx_state = REM_RX_WAIT_WS;
			}
			break;

		case REM_RX_WAIT_1ST_HEX:
			if (a2hex(c , m_rx_data)) {
				m_rx_state = REM_RX_WAIT_2ND_HEX;
			} else {
				m_rx_state = REM_RX_WAIT_WS;
			}
			break;

		case REM_RX_WAIT_2ND_HEX:
			{
				uint8_t tmp;
				if (a2hex(c , tmp)) {
					m_rx_data = (m_rx_data << 4) | tmp;
					m_rx_state = REM_RX_WAIT_SEP;
				} else {
					m_rx_state = REM_RX_WAIT_WS;
				}
			}
			break;

		case REM_RX_WAIT_SEP:
			if (is_terminator(c) || is_space(c)) {
				m_rx_state = REM_RX_WAIT_CH;
				LOG_PARSER("PARSE %02x %d->%d\n" , c , prev_state , m_rx_state);
				data = m_rx_data;
				return m_rx_ch;
			} else {
				m_rx_state = REM_RX_WAIT_WS;
			}
			break;

		case REM_RX_WAIT_WS:
			if (is_terminator(c) || is_space(c)) {
				m_rx_state = REM_RX_WAIT_CH;
			}
			break;

		default:
			m_rx_state = REM_RX_WAIT_CH;
			break;
		}
		LOG_PARSER("PARSE %02x %d->%d\n" , c , prev_state , m_rx_state);
	}
	return 0;
}