static gboolean ResolutionResolutionSetCB(RpcInData *data) { uint32 width = 0 ; uint32 height = 0; unsigned int index = 0; gboolean retval = FALSE; ResolutionInfoType *resInfo = &resolutionInfo; if (!resInfo->initialized) { g_debug("%s: FAIL! Request for resolution set but plugin is not initialized\n", __FUNCTION__); return RPCIN_SETRETVALS(data, "Invalid guest state: resolution set not initialized", FALSE); } /* parse the width and height */ if (!StrUtil_GetNextUintToken(&width, &index, data->args, " ")) { goto invalid_arguments; } if (!StrUtil_GetNextUintToken(&height, &index, data->args, "")) { goto invalid_arguments; } retval = ResolutionSetResolution(width, height); invalid_arguments: return RPCIN_SETRETVALS(data, retval ? "" : "Invalid arguments", retval); }
static gboolean ResolutionChangeHost3DAvailabilityHintCB(RpcInData *data) { unsigned int set; gboolean success = FALSE; unsigned int index = 0; g_debug("%s: enter\n", __FUNCTION__); if (!StrUtil_GetNextUintToken(&set, &index, data->args, " ")) { g_debug("%s: invalid arguments\n", __FUNCTION__); return RPCIN_SETRETVALS(data, "Invalid arguments. Expected \"set\"", FALSE); } success = ResolutionChangeHost3DAvailabilityHint(set?TRUE:FALSE); RPCIN_SETRETVALS(data, success ? "" : "ResolutionChangeHost3DAvailabilityHint failed", success); g_debug("%s: leave\n", __FUNCTION__); return success; }
static VMGuestLibError VMGuestLibUpdateInfo(VMGuestLibHandle handle) // IN { char *reply = NULL; size_t replyLen; VMGuestLibError ret = VMGUESTLIB_ERROR_INVALID_ARG; uint32 hostVersion = HANDLE_VERSION(handle); /* * Starting with the highest supported protocol (major) version, negotiate * down to the highest host supported version. Host supports minimum version * 2. */ if (hostVersion == 0) { hostVersion = VMGUESTLIB_DATA_VERSION; } do { char commandBuf[64]; unsigned int index = 0; /* Free the last reply when retrying. */ free(reply); reply = NULL; /* * Construct command string with the command name and the version * of the data struct that we want. */ Str_Sprintf(commandBuf, sizeof commandBuf, "%s %d", VMGUESTLIB_BACKDOOR_COMMAND_STRING, hostVersion); /* Send the request. */ if (RpcChannel_SendOne(&reply, &replyLen, commandBuf)) { VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply; VMSessionId sessionId = HANDLE_SESSIONID(handle); ASSERT(hostVersion == v2reply->hdr.version); if (sessionId != 0 && sessionId != v2reply->hdr.sessionId) { /* Renegotiate protocol if sessionId changed. */ hostVersion = VMGUESTLIB_DATA_VERSION; HANDLE_SESSIONID(handle) = 0; continue; } ret = VMGUESTLIB_ERROR_SUCCESS; break; } /* * Host is older and doesn't support the requested protocol version. * Request the highest version the host supports. */ Debug("Failed to retrieve info: %s\n", reply ? reply : "NULL"); if (hostVersion == 2 || Str_Strncmp(reply, "Unknown command", sizeof "Unknown command") == 0) { /* * Host does not support this feature. Older (v2) host would return * "Unsupported version" if it doesn't recognize the requested version. * * XXX: Maybe use another error code for this case where the host * product doesn't support this feature? */ ret = VMGUESTLIB_ERROR_NOT_ENABLED; break; } else if (hostVersion == 3) { /* * Host supports v2 at a minimum. If request for v3 fails, then just use * v2, since v2 host does not send the highest supported version in the * reply. */ hostVersion = 2; HANDLE_SESSIONID(handle) = 0; continue; } else if (!StrUtil_GetNextUintToken(&hostVersion, &index, reply, ":")) { /* * v3 and onwards, the host returns the highest major version it supports, * if the requested version is not supported. So parse out the host * version from the reply and return error if it didn't. */ Debug("Bad reply received from host.\n"); ret = VMGUESTLIB_ERROR_OTHER; break; } ASSERT(hostVersion < VMGUESTLIB_DATA_VERSION); } while (ret != VMGUESTLIB_ERROR_SUCCESS); if (ret != VMGUESTLIB_ERROR_SUCCESS) { goto done; } /* Sanity check the results. */ if (replyLen < sizeof hostVersion) { Debug("Unable to retrieve version\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (hostVersion == 2) { VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply; size_t dataSize = sizeof *v2reply; /* More sanity checks. */ if (v2reply->hdr.version != hostVersion) { Debug("Incorrect data version returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (replyLen != dataSize) { Debug("Incorrect data size returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } /* Store the reply in the handle. */ HANDLE_VERSION(handle) = v2reply->hdr.version; HANDLE_SESSIONID(handle) = v2reply->hdr.sessionId; if (HANDLE_DATASIZE(handle) < dataSize) { /* [Re]alloc if the local handle buffer is not big enough. */ free(HANDLE_DATA(handle)); HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize); HANDLE_DATASIZE(handle) = dataSize; } memcpy(HANDLE_DATA(handle), reply, replyLen); /* Make sure resourcePoolPath is NUL terminated. */ v2reply = HANDLE_DATA(handle); v2reply->resourcePoolPath.value[sizeof v2reply->resourcePoolPath.value - 1] = '\0'; ret = VMGUESTLIB_ERROR_SUCCESS; } else if (hostVersion == 3) { VMGuestLibDataV3 *v3reply = (VMGuestLibDataV3 *)reply; size_t dataSize; XDR xdrs; GuestLibV3StatCount count; VMGuestLibStatisticsV3 *v3stats; /* More sanity checks. */ if (v3reply->hdr.version != hostVersion) { Debug("Incorrect data version returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (replyLen < sizeof *v3reply) { Debug("Incorrect data size returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } /* 0. Copy the reply version and sessionId to the handle. */ HANDLE_VERSION(handle) = v3reply->hdr.version; HANDLE_SESSIONID(handle) = v3reply->hdr.sessionId; /* * 1. Retrieve the length of the statistics array from the XDR encoded * part of the reply. */ xdrmem_create(&xdrs, v3reply->data, v3reply->dataSize, XDR_DECODE); if (!xdr_GuestLibV3StatCount(&xdrs, &count)) { xdr_destroy(&xdrs); goto done; } if (count >= GUESTLIB_MAX_STATISTIC_ID) { /* * Host has more than we can process. So process only what this side * can. */ count = GUESTLIB_MAX_STATISTIC_ID - 1; } /* 2. [Re]alloc if the local handle buffer is not big enough. */ dataSize = sizeof *v3stats + (count * sizeof (GuestLibV3Stat)); if (HANDLE_DATASIZE(handle) < dataSize) { free(HANDLE_DATA(handle)); HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize); HANDLE_DATASIZE(handle) = dataSize; } /* 3. Unmarshal the array of statistics. */ v3stats = HANDLE_DATA(handle); v3stats->numStats = count; for (count = 0; count < v3stats->numStats; count++) { GuestLibV3TypeIds statId = count + 1; /* Unmarshal the statistic. */ if (!xdr_GuestLibV3Stat(&xdrs, &v3stats->stats[count])) { break; } /* Host sends all the V3 statistics it supports, in order. */ if (v3stats->stats[count].d != statId) { break; } } if (count >= v3stats->numStats) { ret = VMGUESTLIB_ERROR_SUCCESS; } else { /* * Error while unmarshalling. Deep-free already unmarshalled * statistics and invalidate the data in the handle. */ GuestLibV3StatCount c; for (c = 0; c < count; c++) { VMX_XDR_FREE(xdr_GuestLibV3Stat, &v3stats->stats[c]); } HANDLE_SESSIONID(handle) = 0; } /* 4. Free resources. */ xdr_destroy(&xdrs); } else { /* * Host should never reply with a higher version protocol than requested. */ ret = VMGUESTLIB_ERROR_OTHER; } done: free(reply); return ret; }