2017-06-12 22:13 GMT+02:00 Sri Ramanujam <sramanujam@xxxxxxxxx>: > This commit adds support for virDomainSendKey. It also serves as an > example of how to use the new method invocation APIs with a single > "simple" type parameter. > --- > src/hyperv/hyperv_driver.c | 123 ++++++++++++++++++++++++++++++++++ > src/hyperv/hyperv_wmi.c | 7 ++ > src/hyperv/hyperv_wmi.h | 3 +- > src/hyperv/hyperv_wmi_generator.input | 86 ++++++++++++++++++++++++ > 4 files changed, 218 insertions(+), 1 deletion(-) > > diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c > index 0ca5971..3f5b94e 100644 > --- a/src/hyperv/hyperv_driver.c > +++ b/src/hyperv/hyperv_driver.c > @@ -1373,6 +1375,126 @@ hypervConnectListAllDomains(virConnectPtr conn, > #undef MATCH > > > +static int > +hypervDomainSendKey(virDomainPtr domain, unsigned int codeset, > + unsigned int holdtime, unsigned int *keycodes, int nkeycodes, > + unsigned int flags) > +{ > + int result = -1; > + size_t i = 0; > + int keycode = 0; > + int *translatedKeycodes = NULL; > + hypervPrivate *priv = domain->conn->privateData; > + char uuid_string[VIR_UUID_STRING_BUFLEN]; > + char *selector = NULL; > + Msvm_ComputerSystem *computerSystem = NULL; > + Msvm_Keyboard *keyboard = NULL; > + virBuffer query = VIR_BUFFER_INITIALIZER; > + hypervInvokeParamsListPtr params = NULL; > + char keycodeStr[INT_BUFSIZE_BOUND(int)]; > + > + virCheckFlags(0, -1); > + > + virUUIDFormat(domain->uuid, uuid_string); > + > + if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) > + goto cleanup; > + > + virBufferAsprintf(&query, > + "associators of " > + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," > + "Name=\"%s\"} " > + "where ResultClass = Msvm_Keyboard", > + uuid_string); > + > + if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0) > + goto cleanup; > + > + if (VIR_ALLOC_N(translatedKeycodes, nkeycodes) < 0) > + goto cleanup; > + > + /* translate keycodes to win32 and generate keyup scancodes. */ > + for (i = 0; i < nkeycodes; i++) { > + if (codeset != VIR_KEYCODE_SET_WIN32) { > + keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32, > + keycodes[i]); > + > + if (keycode < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not translate keycode")); > + goto cleanup; > + } > + translatedKeycodes[i] = keycode; > + } > + } > + > + if (virAsprintf(&selector, > + "CreationClassName=Msvm_Keyboard&DeviceID=%s&" > + "SystemCreationClassName=Msvm_ComputerSystem&" > + "SystemName=%s", keyboard->data.common->DeviceID, uuid_string) < 0) > + goto cleanup; > + > + /* press the keys */ > + for (i = 0; i < nkeycodes; i++) { > + params = NULL; Setting params to NULL here is pointless, because the hypervCreateInvokeParamsList result will be assigned to it under all circumstances. > + snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]); > + > + params = hypervCreateInvokeParamsList(priv, "PressKey", selector, > + Msvm_Keyboard_WmiInfo); > + > + if (!params) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create param")); > + goto cleanup; > + } > + > + if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) If hypervAddSimpleParam fails then params will be leaked here. Add a call to hypervFreeInvokeParams here. > + goto cleanup; > + > + if (hypervInvokeMethod(priv, params, NULL) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"), > + translatedKeycodes[i]); > + goto cleanup; > + } > + } > + > + /* simulate holdtime by sleeping */ > + if (holdtime > 0) > + usleep(holdtime * 1000); > + > + /* release the keys */ > + for (i = 0; i < nkeycodes; i++) { > + params = NULL; Setting params to NULL here is pointless, because the hypervCreateInvokeParamsList result will be assigned to it under all circumstances. > + > + snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]); > + params = hypervCreateInvokeParamsList(priv, "ReleaseKey", selector, > + Msvm_Keyboard_WmiInfo); > + > + if (!params) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create param")); > + goto cleanup; > + } > + > + if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) If hypervAddSimpleParam fails then params will be leaked here. Add a call to hypervFreeInvokeParams here. > + goto cleanup; > + > + if (hypervInvokeMethod(priv, params, NULL) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key %s"), > + keycodeStr); > + goto cleanup; > + } > + } > + > + result = 0; > + > + cleanup: > + VIR_FREE(translatedKeycodes); > + VIR_FREE(selector); > + hypervFreeObject(priv, (hypervObject *) keyboard); > + hypervFreeObject(priv, (hypervObject *) computerSystem); > + virBufferFreeAndReset(&query); > + return result; > +} -- Matthias Bolte http://photron.blogspot.com -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list