in vboxguest/vboxguest_core.c [173:229]
static int vbg_report_guest_info(struct vbg_dev *gdev)
{
/*
* Allocate and fill in the two guest info reports.
*/
struct vmmdev_guest_info *req1 = NULL;
struct vmmdev_guest_info2 *req2 = NULL;
int rc, ret = -ENOMEM;
req1 = vbg_req_alloc(sizeof(*req1), VMMDEVREQ_REPORT_GUEST_INFO,
VBG_KERNEL_REQUEST);
req2 = vbg_req_alloc(sizeof(*req2), VMMDEVREQ_REPORT_GUEST_INFO2,
VBG_KERNEL_REQUEST);
if (!req1 || !req2)
goto out_free;
req1->interface_version = VMMDEV_VERSION;
req1->os_type = VMMDEV_OSTYPE_LINUX26;
#if __BITS_PER_LONG == 64
req1->os_type |= VMMDEV_OSTYPE_X64;
#endif
req2->additions_major = VBG_VERSION_MAJOR;
req2->additions_minor = VBG_VERSION_MINOR;
req2->additions_build = VBG_VERSION_BUILD;
req2->additions_revision = VBG_SVN_REV;
req2->additions_features =
VMMDEV_GUEST_INFO2_ADDITIONS_FEATURES_REQUESTOR_INFO;
strlcpy(req2->name, VBG_VERSION_STRING,
sizeof(req2->name));
/*
* There are two protocols here:
* 1. INFO2 + INFO1. Supported by >=3.2.51.
* 2. INFO1 and optionally INFO2. The old protocol.
*
* We try protocol 2 first. It will fail with VERR_NOT_SUPPORTED
* if not supported by the VMMDev (message ordering requirement).
*/
rc = vbg_req_perform(gdev, req2);
if (rc >= 0) {
rc = vbg_req_perform(gdev, req1);
} else if (rc == VERR_NOT_SUPPORTED || rc == VERR_NOT_IMPLEMENTED) {
rc = vbg_req_perform(gdev, req1);
if (rc >= 0) {
rc = vbg_req_perform(gdev, req2);
if (rc == VERR_NOT_IMPLEMENTED)
rc = VINF_SUCCESS;
}
}
ret = vbg_status_code_to_errno(rc);
out_free:
vbg_req_free(req2, sizeof(*req2));
vbg_req_free(req1, sizeof(*req1));
return ret;
}