[ovs-dev] [PATCH 1/3 v7] Windows: Add internal switch port per OVS bridge

Sairam Venugopal vsairam at vmware.com
Tue Dec 20 05:56:08 UTC 2016


Thanks for the patch!

Acked-by: Sairam Venugopal <vsairam at vmware.com>


On 12/15/16, 11:37 AM, "Alin Serdean" <aserdean at cloudbasesolutions.com>
wrote:

>This patch updates the following commands in the vswitch:
> ovs-vsctl add-br br-test
> ovs-vsctl del-br br-test
>
>ovs-vsctl add-br br-test:
>    This command will now create an internal port on the MSFT virtual
>switch
>  using the WMI interface from Msvm_VirtualEthernetSwitchManagementService
>  leveraging the method AddResourceSettings.
>    Before creating the actual port, the switch will be queried to see if
>there
>  is not a port already created (good for restarts when restarting the
>  vswitch daemon). If there is a port defined it will return success and
>log
>  a message.
>    After checking if the port already exists the command will also verify
>  if the forwarding extension (windows datapath) is enabled and on a
>single
>  switch. If it is not activated or if it is activated on multiple
>switches
>  it will return an error and a message will be logged.
>    After the port was created on the switch, we will disable the adapter
>on
>  the host and rename to the corresponding OVS bridge name for
>consistency.
>    The user will enable and set the values he wants after creation.
>
>ovs-vsctl del-br br-test
>    This command will remove an internal port on the MSFT virtual switch
>  using the Msvm_VirtualEthernetSwitchManagementService class and
>executing
>  the method RemoveResourceSettings.
>
>Both commands will be blocking until the WMI job is finished, this allows
>us
>to guarantee that the ports are created and their name are set before
>issuing
>a netlink message to the windows datapath.
>
>This patch also includes helpers for normal WMI retrievals and
>initializations.
>Appveyor and documentation has been modified to include the libraries
>needed
>for COM objects.
>
>This patch was tested individually using IMallocSpy and CRT heap checks
>to ensure no new memory leaks are introduced.
>
>Tested on the following OS's:
>Windows 2012, Windows 2012r2, Windows 2016
>
>Signed-off-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com>
>Acked-by: Paul Boca <pboca at cloudbasesolutions.com>
>---
>v7: rebase
>v6: rebase
>v5: rebase
>v4: address comments (sanitize input, short refactor)
>    use full stop on comments
>    update coding style
>v3: rebase, add acked
>v2: Address comments. Rebase
>---
> appveyor.yml       |    2 +-
> lib/automake.mk    |    4 +-
> lib/dpif-netlink.c |   21 +
> lib/wmi.c          | 1277
>++++++++++++++++++++++++++++++++++++++++++++++++++++
> lib/wmi.h          |   51 +++
> 5 files changed, 1353 insertions(+), 2 deletions(-)
> create mode 100644 lib/wmi.c
> create mode 100644 lib/wmi.h
>
>diff --git a/appveyor.yml b/appveyor.yml
>index 8a6694b..51bae11 100644
>--- a/appveyor.yml
>+++ b/appveyor.yml
>@@ -41,5 +41,5 @@ build_script:
> - C:\MinGW\msys\1.0\bin\bash -lc "cp
>/c/pthreads-win32/Pre-built.2/dll/x86/*.dll /c/openvswitch/."
> - C:\MinGW\msys\1.0\bin\bash -lc "mv /bin/link.exe /bin/link_copy.exe"
> - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./boot.sh"
>-- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure
>CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi\"
>--with-pthread=C:/pthreads-win32/Pre-built.2
>--with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\""
>+- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure
>CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi
>-lwbemuuid -lole32 -loleaut32\"
>--with-pthread=C:/pthreads-win32/Pre-built.2
>--with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\""
> - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && make"
>diff --git a/lib/automake.mk b/lib/automake.mk
>index 9345cee..88344a3 100644
>--- a/lib/automake.mk
>+++ b/lib/automake.mk
>@@ -388,7 +388,9 @@ lib_libopenvswitch_la_SOURCES += \
> 	lib/netlink-notifier.h \
> 	lib/netlink-protocol.h \
> 	lib/netlink-socket.c \
>-	lib/netlink-socket.h
>+	lib/netlink-socket.h \
>+	lib/wmi.c \
>+	lib/wmi.h
> endif
> 
> if HAVE_POSIX_AIO
>diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
>index a39faa2..c8b0e37 100644
>--- a/lib/dpif-netlink.c
>+++ b/lib/dpif-netlink.c
>@@ -58,6 +58,7 @@
> 
> VLOG_DEFINE_THIS_MODULE(dpif_netlink);
> #ifdef _WIN32
>+#include "wmi.h"
> enum { WINDOWS = 1 };
> #else
> enum { WINDOWS = 0 };
>@@ -849,6 +850,16 @@ dpif_netlink_port_add__(struct dpif_netlink *dpif,
>struct netdev *netdev,
> #endif
>     }
> 
>+#ifdef _WIN32
>+    if (request.type == OVS_VPORT_TYPE_INTERNAL) {
>+        if (!create_wmi_port(name)){
>+            VLOG_ERR("Could not create wmi internal port with name:%s",
>name);
>+            vport_del_socksp(dpif, socksp);
>+            return EINVAL;
>+        };
>+    }
>+#endif
>+
>     tnl_cfg = netdev_get_tunnel_config(netdev);
>     if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) {
>         ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
>@@ -940,6 +951,16 @@ dpif_netlink_port_del__(struct dpif_netlink *dpif,
>odp_port_t port_no)
>     vport.cmd = OVS_VPORT_CMD_DEL;
>     vport.dp_ifindex = dpif->dp_ifindex;
>     vport.port_no = port_no;
>+#ifdef _WIN32
>+    struct dpif_port temp_dpif_port;
>+    dpif_netlink_port_query__(dpif, port_no, NULL, &temp_dpif_port);
>+    if (!strcmp(temp_dpif_port.type, "internal")) {
>+        if (!delete_wmi_port(temp_dpif_port.name)){
>+            VLOG_ERR("Could not delete wmi port with name: %s",
>+                     temp_dpif_port.name);
>+        };
>+    }
>+#endif
>     error = dpif_netlink_vport_transact(&vport, NULL, NULL);
> 
>     vport_del_channels(dpif, port_no);
>diff --git a/lib/wmi.c b/lib/wmi.c
>new file mode 100644
>index 0000000..e38b482
>--- /dev/null
>+++ b/lib/wmi.c
>@@ -0,0 +1,1277 @@
>+/*
>+ * Copyright (c) 2016 Cloudbase Solutions Srl
>+ *
>+ * Licensed under the Apache License, Version 2.0 (the "License");
>+ * you may not use this file except in compliance with the License.
>+ * You may obtain a copy of the License at
>+ *
>+ *     
>https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_license
>s_LICENSE-2D2.0&d=DgICAg&c=uilaK90D4TOVoH58JNXRgQ&r=Z6vowHUOjP5ysP_g372c49
>Nqc1vEKqHKNBkR5Q5Z7uo&m=bdxpwofizlzMhsYoOZoiq0yLJLSasRgmPwO00fUs_FY&s=wMJX
>-nHXxCR4etVk9vFL5012RjwlTwObSTej5EdAIj8&e=
>+ *
>+ * Unless required by applicable law or agreed to in writing, software
>+ * distributed under the License is distributed on an "AS IS" BASIS,
>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>implied.
>+ * See the License for the specific language governing permissions and
>+ * limitations under the License.
>+ */
>+
>+#include <config.h>
>+#include "wmi.h"
>+#include <stdlib.h>
>+#include <stdio.h>
>+#include <tchar.h>
>+#include "openvswitch/vlog.h"
>+
>+VLOG_DEFINE_THIS_MODULE(wmi);
>+
>+/* WMI Job values. */
>+enum job_status
>+{
>+    job_starting = 3,
>+    job_running = 4,
>+    job_completed = 7,
>+    job_wait = 4096
>+};
>+
>+static char *
>+sanitize_port_name(char *name)
>+{
>+    char *p1, *p2;
>+    p1 = p2 = name;
>+
>+    while (*p1) {
>+        if ((*p1) == '\'' || (*p1) == '\"') {
>+            p1++;
>+        } else {
>+            *p2 = *p1;
>+            p2++;
>+            p1++;
>+        }
>+    }
>+    *p2 = '\0';
>+    return name;
>+}
>+
>+/* This function will output the appropriate message for a given
>HRESULT.*/
>+static void
>+get_hres_error(HRESULT hres)
>+{
>+    char *error_msg = NULL;
>+
>+    if (FACILITY_WINDOWS == HRESULT_FACILITY(hres)) {
>+        hres = HRESULT_CODE(hres);
>+    }
>+
>+    VLOG_ERR("%s", ovs_format_message(hres));
>+}
>+
>+static boolean
>+check_return_value(HRESULT hres)
>+{
>+    if (FAILED(hres)) {
>+        get_hres_error(hres);
>+        return false;
>+    }
>+
>+    return true;
>+}
>+
>+static HRESULT
>+get_variant_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>+                  VARIANT *value)
>+{
>+    HRESULT hres;
>+
>+    VariantInit(value);
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, field_name, 0, value, 0, 0);
>+
>+    if (FAILED(hres)) {
>+        VariantClear(value);
>+    }
>+
>+    return hres;
>+}
>+
>+/* This function retrieves the uint16_t value from a given class object
>with
>+ * the field name field_name. */
>+static HRESULT
>+get_uint16_t_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>+                   uint16_t *value)
>+{
>+    VARIANT vt_prop;
>+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>+    *value = V_UI2(&vt_prop);
>+
>+    return hres;
>+}
>+
>+/* This function retrieves the unsigned int values from a given class
>object
>+ * with the field name field_name. */
>+static HRESULT
>+get_uint_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>+               unsigned int *value)
>+{
>+    VARIANT vt_prop;
>+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>+    *value = V_UI4(&vt_prop);
>+
>+    return hres;
>+}
>+
>+/* This function retrieves the unsigned short value from a given class
>object
>+ * with the field name field_name. */
>+static HRESULT
>+get_ushort_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>+                 unsigned short *value)
>+{
>+    VARIANT vt_prop;
>+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>+    *value = V_UI2(&vt_prop);
>+
>+    return hres;
>+}
>+
>+/* This function retrieves the BSTR value from a given class object with
>+ * the field name field_name, to a preallocated destination dest and
>with the
>+ * maximum length max_dest_lgth. */
>+static HRESULT
>+get_str_value(IWbemClassObject *pcls_obj, wchar_t *field_name, wchar_t
>*dest,
>+              int max_dest_lgth)
>+{
>+    VARIANT vt_prop;
>+    HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>+
>+    if (wcscpy_s(dest, max_dest_lgth, vt_prop.bstrVal)) {
>+        VariantClear(&vt_prop);
>+        VLOG_WARN("get_str_value, wcscpy_s failed :%s",
>ovs_strerror(errno));
>+        return WBEM_E_FAILED;
>+    }
>+
>+    VariantClear(&vt_prop);
>+    return S_OK;
>+}
>+
>+/* This function waits for a WMI job to finish and retrieves the error
>code
>+ * if the job failed */
>+static HRESULT
>+wait_for_job(IWbemServices *psvc, wchar_t *job_path)
>+{
>+    IWbemClassObject *pcls_obj = NULL;
>+    HRESULT retval = 0;
>+    uint16_t job_state = 0;
>+    uint16_t error = 0;
>+
>+    do {
>+        if(!check_return_value(psvc->lpVtbl->GetObject(psvc, job_path,
>0, NULL,
>+                                                       &pcls_obj,
>NULL))) {
>+            retval = WBEM_E_FAILED;
>+            break;
>+        }
>+
>+        retval = get_uint16_t_value(pcls_obj, L"JobState", &job_state);
>+        if (FAILED(retval)) {
>+            break;
>+        }
>+
>+        if (job_state == job_starting || job_state == job_running) {
>+            Sleep(200);
>+        } else if (job_state == job_completed) {
>+            break;
>+        } else {
>+            /* Error occurred. */
>+            retval = get_uint16_t_value(pcls_obj, L"ErrorCode", &error);
>+            if (FAILED(retval)) {
>+                break;
>+            }
>+            VLOG_WARN("Job failed with error: %d", error);
>+            retval = WBEM_E_FAILED;;
>+            break;
>+        }
>+
>+        if (pcls_obj != NULL) {
>+            pcls_obj->lpVtbl->Release(pcls_obj);
>+            pcls_obj = NULL;
>+        }
>+    } while(TRUE);
>+
>+    if (pcls_obj != NULL) {
>+        pcls_obj->lpVtbl->Release(pcls_obj);
>+        pcls_obj = NULL;
>+    }
>+
>+    return retval;
>+}
>+
>+/* This function will initialize DCOM retrieving the WMI locator's ploc
>and
>+ * the context associated to it. */
>+static boolean
>+initialize_wmi(IWbemLocator **ploc, IWbemContext **pcontext)
>+{
>+    HRESULT hres = 0;
>+
>+    /* Initialize COM. */
>+    hres = CoInitialize(NULL);
>+
>+    if (FAILED(hres)) {
>+        return false;
>+    }
>+
>+    /* Initialize COM security. */
>+    hres = CoInitializeSecurity(NULL,
>+                                -1,
>+                                NULL,
>+                                NULL,
>+                                RPC_C_AUTHN_LEVEL_DEFAULT,
>+                                RPC_C_IMP_LEVEL_IMPERSONATE,
>+                                NULL,
>+                                EOAC_NONE,
>+                                NULL);
>+
>+    if (FAILED(hres)) {
>+        return false;
>+    }
>+
>+    /* Fill context. */
>+    hres = CoCreateInstance(&CLSID_WbemContext,
>+                            NULL,
>+                            CLSCTX_INPROC_SERVER,
>+                            &IID_IWbemContext,
>+                            (void**)pcontext);
>+
>+    if (FAILED(hres)) {
>+        return false;
>+    }
>+
>+    fill_context(*pcontext);
>+
>+    /* Initialize locator's (ploc) to WMI. */
>+    hres = CoCreateInstance(&CLSID_WbemLocator,
>+                            NULL,
>+                            CLSCTX_INPROC_SERVER,
>+                            &IID_IWbemLocator,
>+                            (LPVOID *)ploc);
>+
>+    if (FAILED(hres)) {
>+        return false;
>+    }
>+
>+    return true;
>+}
>+
>+/* This function connects the WMI locator's ploc to a given WMI provider
>+ * defined in server and also sets the required security levels for a
>local
>+ * connection to it. */
>+static boolean
>+connect_set_security(IWbemLocator *ploc, IWbemContext *pcontext,
>+                     wchar_t *server, IWbemServices **psvc)
>+{
>+    HRESULT hres = 0;
>+
>+   /* Connect to server. */
>+    hres = ploc->lpVtbl->ConnectServer(ploc,
>+                                       server,
>+                                       NULL,
>+                                       NULL,
>+                                       0,
>+                                       0,
>+                                       0,
>+                                       pcontext,
>+                                       psvc);
>+
>+    if (FAILED(hres)) {
>+        return false;
>+    }
>+
>+    /* Set security levels. */
>+    hres = CoSetProxyBlanket((IUnknown *) *psvc,
>+                             RPC_C_AUTHN_WINNT,
>+                             RPC_C_AUTHZ_NONE,
>+                             NULL,
>+                             RPC_C_AUTHN_LEVEL_CALL,
>+                             RPC_C_IMP_LEVEL_IMPERSONATE,
>+                             NULL,
>+                             EOAC_NONE);
>+
>+    if (FAILED(hres)) {
>+        return false;
>+    }
>+
>+    return true;
>+}
>+
>+/* This function retrieves the first class object of a given enumeration
>+ * outputted by a query and fails if it could not retrieve the object or
>there
>+ * was no object to retrieve */
>+static boolean
>+get_first_element(IEnumWbemClassObject *penumerate,
>+                  IWbemClassObject **pcls_obj)
>+{
>+    unsigned long retval = 0;
>+
>+    if (penumerate == NULL) {
>+        VLOG_WARN("Enumeration Class Object is NULL. Cannot get the
>first"
>+                  "object");
>+        return false;
>+    }
>+
>+    HRESULT hres = penumerate->lpVtbl->Next(penumerate, WBEM_INFINITE, 1,
>+                                            pcls_obj, &retval);
>+
>+
>+    if (!check_return_value(hres) || retval == 0) {
>+        return false;
>+    }
>+
>+    return true;
>+}
>+
>+/* This function is a wrapper that transforms a char * into a wchar_t *
>*/
>+static boolean
>+tranform_wide(char *name, wchar_t *wide_name)
>+{
>+    unsigned long size = strlen(name) + 1;
>+    long long ret = 0;
>+
>+    if (wide_name == NULL) {
>+        VLOG_WARN("Provided wide string is NULL");
>+        return false;
>+    }
>+
>+    ret = mbstowcs(wide_name, name, size);
>+
>+    if (ret == -1) {
>+        VLOG_WARN("Invalid multibyte character is encountered");
>+        return false;
>+    } else if (ret == size) {
>+        VLOG_WARN("Returned wide string not NULL terminated");
>+        return false;
>+    }
>+
>+    return true;
>+}
>+
>+/* This function will delete a switch internal port with a given name as
>input
>+ * executing "RemoveResourceSettings" as per documentation:
>+ * 
>https://urldefense.proofpoint.com/v2/url?u=https-3A__msdn.microsoft.com_en
>-2Dus_library_hh850277-2528v-3Dvs.85-2529.aspx&d=DgICAg&c=uilaK90D4TOVoH58
>JNXRgQ&r=Z6vowHUOjP5ysP_g372c49Nqc1vEKqHKNBkR5Q5Z7uo&m=bdxpwofizlzMhsYoOZo
>iq0yLJLSasRgmPwO00fUs_FY&s=5cNHlXFRz5CeSD8wnl8KO5qKM4zkrvWQEmWVetfmHXc&e=
>+ * allocating the data and populating the needed fields to execute the
>+ * method */
>+boolean
>+delete_wmi_port(char *name)
>+{
>+    HRESULT hres = 0;
>+    boolean retval = true;
>+
>+    IWbemLocator *ploc = NULL;
>+    IWbemServices *psvc = NULL;
>+    IWbemContext *pcontext = NULL;
>+    IWbemClassObject *pclass_instance = NULL;
>+    IWbemClassObject *pinput_params = NULL;
>+    IWbemClassObject *pcls_obj = NULL;
>+    IWbemClassObject *pout_params = NULL;
>+    IEnumWbemClassObject *penumerate = NULL;
>+
>+    sanitize_port_name(name);
>+    VARIANT vt_prop;
>+    VARIANT variant_array;
>+    wchar_t *wide_name = NULL;
>+    VariantInit(&vt_prop);
>+    VariantInit(&variant_array);
>+
>+    LONG count[1];
>+    SAFEARRAY* psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
>+    if (psa == NULL) {
>+        VLOG_WARN("Could not allocate memory for a SAFEARRAY");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!initialize_wmi(&ploc, &pcontext)) {
>+        VLOG_WARN("Could not initialize DCOM");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!connect_set_security(ploc, pcontext,
>L"Root\\Virtualization\\v2",
>+                              &psvc)) {
>+        VLOG_WARN("Could not connect and set security for
>virtualization");
>+        retval = false;
>+        goto error;
>+    }
>+
>+
>+    /* Get the port with the element name equal to the name input. */
>+    wchar_t internal_port_query[2048] = L"SELECT * from "
>+        L"Msvm_EthernetPortAllocationSettingData  WHERE ElementName =
>\"" ;
>+
>+    wide_name = malloc((strlen(name) + 1) * sizeof(wchar_t));
>+    if (wide_name == NULL) {
>+        VLOG_WARN("Could not allocate memory for wide string");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!tranform_wide(name, wide_name)) {
>+        retval = false;
>+        goto error;
>+    }
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>wide_name);
>+
>+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
>+
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   internal_port_query,
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Get the element path on the switch which will be deleted. */
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    /* Get the class object and the parameters it can have. */
>+    hres = psvc->lpVtbl->GetObject(psvc,
>+        L"Msvm_VirtualEthernetSwitchManagementService", 0, NULL,
>&pcls_obj,
>+        NULL);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = pcls_obj->lpVtbl->GetMethod(pcls_obj,
>L"RemoveResourceSettings", 0,
>+                                       &pinput_params, NULL);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
>+                                                &pclass_instance);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    count[0] = 0;
>+
>+    hres = SafeArrayPutElement(psa, count, vt_prop.bstrVal);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    VariantClear(&vt_prop);
>+    VariantInit(&vt_prop);
>+    variant_array.vt = VT_ARRAY | VT_BSTR;
>+    variant_array.parray = psa;
>+
>+    hres = pclass_instance->lpVtbl->Put(pclass_instance,
>L"ResourceSettings", 0,
>+                                        &variant_array, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Get the object of the Msvm_VirtualEthernetSwitchManagementService
>which
>+     * we need to invoke the port deletion. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   L"SELECT * FROM "
>+                 
>L"Msvm_VirtualEthernetSwitchManagementService",
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    /* Invoke the delete port method. */
>+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
>+                                    L"RemoveResourceSettings", 0,
>+                                    pcontext, pclass_instance,
>&pout_params,
>+                                    NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    VariantClear(&vt_prop);
>+    VariantInit(&vt_prop);
>+
>+    hres = pout_params->lpVtbl->Get(pout_params, L"ReturnValue", 0,
>+                                    &vt_prop, NULL, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    unsigned int retvalue = 0;
>+    hres = get_uint_value(pout_params, L"ReturnValue", &retvalue);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (retvalue != 0 && retvalue != job_wait) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (retvalue == job_wait) {
>+        WCHAR job_path[2048];
>+        hres = get_str_value(pout_params, L"Job", job_path,
>+                             sizeof(job_path) / sizeof(WCHAR));
>+        if (FAILED(hres)) {
>+            retval = false;
>+            goto error;
>+    }
>+        hres = wait_for_job(psvc, job_path);
>+        if (FAILED(hres)) {
>+            retval = false;
>+        }
>+    }
>+
>+error:
>+    VariantClear(&vt_prop);
>+
>+    if (pcontext != NULL) {
>+        pcontext->lpVtbl->Release(pcontext);
>+        pcontext = NULL;
>+    }
>+    if (psa != NULL) {
>+        SafeArrayDestroy(psa);
>+        psa = NULL;
>+    }
>+    if (pcls_obj != NULL) {
>+        pcls_obj->lpVtbl->Release(pcls_obj);
>+        pcls_obj = NULL;
>+    }
>+    if (wide_name != NULL) {
>+        free(wide_name);
>+        wide_name = NULL;
>+    }
>+    if (!retval) {
>+        get_hres_error(hres);
>+    }
>+    if (pinput_params != NULL) {
>+        pinput_params->lpVtbl->Release(pinput_params);
>+        pinput_params = NULL;
>+    }
>+    if (pout_params != NULL) {
>+        pout_params->lpVtbl->Release(pout_params);
>+        pout_params = NULL;
>+    }
>+    if (psvc != NULL) {
>+        psvc->lpVtbl->Release(psvc);
>+        psvc = NULL;
>+    }
>+    if (ploc != NULL) {
>+        ploc->lpVtbl->Release(ploc);
>+        ploc = NULL;
>+    }
>+    if (pclass_instance != NULL) {
>+        pclass_instance->lpVtbl->Release(pclass_instance);
>+        pclass_instance = NULL;
>+    }
>+    if (penumerate != NULL) {
>+        penumerate->lpVtbl->Release(penumerate);
>+        penumerate = NULL;
>+    }
>+
>+    CoUninitialize();
>+    return retval;
>+}
>+
>+/* This function will create an internal port on the switch given a
>given name
>+ * executing the method AddResourceSettings as per documentation:
>+ * 
>https://urldefense.proofpoint.com/v2/url?u=https-3A__msdn.microsoft.com_en
>-2Dus_library_hh850019-2528v-3Dvs.85-2529.aspx&d=DgICAg&c=uilaK90D4TOVoH58
>JNXRgQ&r=Z6vowHUOjP5ysP_g372c49Nqc1vEKqHKNBkR5Q5Z7uo&m=bdxpwofizlzMhsYoOZo
>iq0yLJLSasRgmPwO00fUs_FY&s=zo6KU4Q0m2GJznJY9FUdNwGV8t0bOMMVIg0v5hl3nCE&e=
>.
>+ * It will verify if the port is already defined, in which case it will
>use
>+ * the specific port, and if the forwarding extension "Open vSwitch
>Extension"
>+ * is enabled and running only on a single switch.
>+ * After the port is created and bound to the switch we will disable the
>+ * created net adapter and rename it to match the OVS bridge name .*/
>+boolean
>+create_wmi_port(char *name) {
>+    HRESULT hres = 0;
>+    boolean retval = true;
>+
>+    BSTR text_object_string = NULL;
>+
>+    IWbemLocator *ploc = NULL;
>+    IWbemContext *pcontext = NULL;
>+    IWbemServices *psvc = NULL;
>+    IEnumWbemClassObject *penumerate = NULL;
>+    IWbemClassObject *default_settings_data = NULL;
>+    IWbemClassObject *default_system = NULL;
>+    IWbemClassObject *pcls_obj = NULL;
>+    IWbemClassObject *pclass = NULL;
>+    IWbemClassObject *pinput_params = NULL;
>+    IWbemClassObject *pclass_instance = NULL;
>+    IWbemObjectTextSrc *text_object = NULL;
>+    IWbemClassObject *pout_params = NULL;
>+
>+    wchar_t *wide_name = NULL;
>+    VARIANT vt_prop;
>+    VARIANT switch_setting_path;
>+    VARIANT new_name;
>+    SAFEARRAY *psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
>+    VARIANT variant_array;
>+    LONG count[1];
>+
>+    VariantInit(&vt_prop);
>+    VariantInit(&switch_setting_path);
>+    sanitize_port_name(name);
>+
>+    if (psa == NULL) {
>+        VLOG_WARN("Could not allocate memory for a SAFEARRAY");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!initialize_wmi(&ploc, &pcontext)) {
>+        VLOG_WARN("Could not initialize DCOM");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!connect_set_security(ploc, pcontext,
>L"Root\\Virtualization\\v2",
>+                              &psvc)) {
>+        VLOG_WARN("Could not connect and set security for
>virtualization");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Check if the element already exists on the switch. */
>+    wchar_t internal_port_query[2048] = L"SELECT * FROM "
>+    L"Msvm_InternalEthernetPort WHERE ElementName = \"";
>+
>+    wide_name = malloc((strlen(name) + 1) * sizeof(wchar_t));
>+    if (wide_name == NULL) {
>+        VLOG_WARN("Could not allocate memory for wide string");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!tranform_wide(name, wide_name)) {
>+        retval = false;
>+        goto error;
>+    }
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>wide_name);
>+
>+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   internal_port_query,
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("Port with name: %s already defined on the switch",
>name);
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    /* Check if the extension is enabled and running.  Also check if the
>+     * the extension is enabled on more than one switch. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   L"SELECT * "
>+                                   L"FROM Msvm_EthernetSwitchExtension "
>+                                   L"WHERE "
>+                                   L"ElementName=\"Open vSwitch
>Extension\" "
>+                                   L"AND EnabledState=2 "
>+                                   L"AND HealthState=5",
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("Open vSwitch Extension is not enabled on any switch");
>+        retval = false;
>+        goto error;
>+    }
>+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
>+             L"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name =
>\"");
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"SystemName", 0,
>+                                 &vt_prop, 0, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>+             vt_prop.bstrVal);
>+
>+    VariantClear(&vt_prop);
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    if (get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("The extension is activated on more than one switch, "
>+                  "aborting operation. Please activate the extension on
>a "
>+                  "single switch");
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+    if (pcls_obj != NULL) {
>+        pcls_obj->lpVtbl->Release(pcls_obj);
>+        pcls_obj = NULL;
>+    }
>+
>+    /* Get the switch object on which the extension is activated. */
>+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   internal_port_query,
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("Could not get the switch object on which the
>extension is"
>+                  "activated");
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"ElementName", 0, &vt_prop,
>0, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
>+             L"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData WHERE
>"
>+             L"ElementName = \"");
>+
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>+             vt_prop.bstrVal);
>+    VariantClear(&vt_prop);
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"Name", 0, &vt_prop, 0, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    /* Should be enough to give the InstanceID, from msdn documentation:
>+     * Uniquely identifies an instance of this class. This property is
>+     * inherited from CIM_SettingData and is always
>+     * set to "Microsoft:GUID\DeviceSpecificData". */
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>+             L"\" AND InstanceID  = \"Microsoft:");
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>+             vt_prop.bstrVal);
>+    wcscat_s(internal_port_query, sizeof(internal_port_query),
>+             L"\"");
>+
>+    VariantClear(&vt_prop);
>+
>+    /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to the
>switch
>+     * object on which the extension is activated. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   internal_port_query,
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("Could not get the first "
>+                  "Msvm_VirtualEthernetSwitchSettingData object");
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, 
>&switch_setting_path,
>+                                 0, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    /* Retrieve a default allocation port.  This object will be later 
>filled
>+     * with optional data to create an switch internal port. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   L"SELECT * FROM "
>+                                   
>L"Msvm_EthernetPortAllocationSettingData "
>+                                   L"WHERE InstanceID LIKE 
>'%%%%\\\\Default' "
>+                                   L"AND ResourceSubType = "
>+                                   L"'Microsoft:Hyper-V:Ethernet 
>Connection'",
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &default_settings_data)) {
>+        VLOG_WARN("Could not retrieve default allocation port object");
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    /* Retrieve the default computer system on which the port allocation 
>will
>+     * be hosted.
>+     * Instead of querying using Description, we can query using 
>InstallDate.
>+     * From MSDN documentation regarding InstallDate:
>+     * The date and time the virtual machine configuration was created 
>for
>+     * a virtual machine, or Null, for a management operating system. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   L"SELECT * FROM Msvm_ComputerSystem 
>WHERE "
>+                                   L"InstallDate is NULL",
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &default_system)) {
>+        VLOG_WARN("Could not retrieve default computer system object");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = default_system->lpVtbl->Get(default_system, L"__PATH",
>+                                       0, &vt_prop, 0, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    count[0] = 0;
>+    hres = SafeArrayPutElement(psa, count, vt_prop.bstrVal);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    VariantClear(&vt_prop);
>+    variant_array.vt = VT_ARRAY | VT_BSTR;
>+    variant_array.parray = psa;
>+    hres = default_settings_data->lpVtbl->Put(default_settings_data,
>+                                              L"HostResource", 0,
>+                                              &variant_array, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = psvc->lpVtbl->GetObject(psvc,
>+                                   
>L"Msvm_VirtualEthernetSwitchManagementService",
>+                                   0, NULL, &pclass, NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = pclass->lpVtbl->GetMethod(pclass, L"AddResourceSettings", 0,
>+                                     &pinput_params, NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
>+                                                &pclass_instance);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Store the switch setting path retrieved above in the affected
>+     * configuration field of the class instance. */
>+    hres = pclass_instance->lpVtbl->Put(pclass_instance,
>+                                        L"AffectedConfiguration", 0,
>+                                        &switch_setting_path, 0);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Store the port name in the ElementName field of the default 
>allocation
>+     * data. */
>+    vt_prop.vt = VT_BSTR;
>+    vt_prop.bstrVal = SysAllocString(wide_name);
>+    hres = default_settings_data->lpVtbl->Put(default_settings_data,
>+                                              L"ElementName", 0,
>+                                              &vt_prop, 0);
>+    VariantClear(&vt_prop);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Retrieve and store the serialized data of the modified default 
>switch
>+     * settings data. */
>+    hres = CoCreateInstance(&CLSID_WbemObjectTextSrc,
>+                            NULL,
>+                            CLSCTX_INPROC_SERVER,
>+                            &IID_IWbemObjectTextSrc,
>+                            (void**)&text_object);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = text_object->lpVtbl->GetText(text_object, 0,
>+                                        default_settings_data,
>+                                        WMI_OBJ_TEXT_WMI_DTD_2_0,
>+                                        pcontext,
>+                                        &text_object_string);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    hres = SafeArrayDestroy(psa);
>+    if (FAILED(hres)) {
>+        VLOG_WARN("Could not clear the data of the array");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
>+
>+    if (psa == NULL) {
>+        VLOG_WARN("Could not allocate memory for a SAFEARRAY");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    count[0] = 0;
>+    variant_array.parray = psa;
>+    hres = SafeArrayPutElement(psa, count, text_object_string);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    hres = pclass_instance->lpVtbl->Put(pclass_instance, 
>L"ResourceSettings",
>+                                        0, &variant_array, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    /* Get the object of the switch service. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   L"SELECT * FROM "
>+                                   
>L"Msvm_VirtualEthernetSwitchManagementService",
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("Could not get the object of the switch service");
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+
>+    hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    /* Try to add the port to the switch. */
>+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
>+                                    L"AddResourceSettings", 0,
>+                                    pcontext, pclass_instance, 
>&pout_params,
>+                                    NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    unsigned int retvalue = 0;
>+    hres = get_uint_value(pout_params, L"ReturnValue", &retvalue);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (retvalue != 0 && retvalue != job_wait) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    if (retvalue == job_wait) {
>+        WCHAR job_path[2048];
>+        hres = get_str_value(pout_params, L"Job", job_path,
>+                             sizeof(job_path) / sizeof(WCHAR));
>+        if (FAILED(hres)) {
>+            retval = false;
>+            goto error;
>+        }
>+        hres = wait_for_job(psvc, job_path);
>+        if (FAILED(hres)) {
>+            retval = false;
>+            goto error;
>+        }
>+    }
>+
>+    pclass->lpVtbl->Release(pclass);
>+    pclass = NULL;
>+    pclass_instance->lpVtbl->Release(pclass_instance);
>+    pclass_instance = NULL;
>+    pinput_params->lpVtbl->Release(pinput_params);
>+    pinput_params = NULL;
>+    psvc->lpVtbl->Release(psvc);
>+    psvc = NULL;
>+    VariantClear(&vt_prop);
>+
>+    if (!connect_set_security(ploc, pcontext, L"Root\\StandardCimv2",
>+                              &psvc)) {
>+        VLOG_WARN("Could not connect and set security for CIM");
>+        retval = false;
>+        goto error;
>+    }
>+
>+    wcscpy_s(internal_port_query, sizeof(internal_port_query),
>+             L"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
>+    wcscat_s(internal_port_query, sizeof(internal_port_query), 
>wide_name);
>+    wcscat_s(internal_port_query, sizeof(internal_port_query), L"%%'");
>+
>+    /* Get the object with the port name equal to name on the CIM. */
>+    hres = psvc->lpVtbl->ExecQuery(psvc,
>+                                   L"WQL",
>+                                   internal_port_query,
>+                                   WBEM_FLAG_FORWARD_ONLY |
>+                                   WBEM_FLAG_RETURN_IMMEDIATELY,
>+                                   NULL,
>+                                   &penumerate);
>+
>+    if (!get_first_element(penumerate, &pcls_obj)) {
>+        VLOG_WARN("Element name: %s not found in CIM", name);
>+        retval = false;
>+        goto error;
>+    }
>+    penumerate->lpVtbl->Release(penumerate);
>+    penumerate = NULL;
>+    pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
>+    pcls_obj->lpVtbl->Release(pcls_obj);
>+    pcls_obj = NULL;
>+
>+    /* Disable the adapter with port name equal with name. */
>+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal, L"Disable", 0,
>+                                    pcontext, NULL, NULL, NULL);
>+
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = psvc->lpVtbl->GetObject(psvc, L"MSFT_NetAdapter", 0, NULL, 
>&pclass,
>+                                   NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = pclass->lpVtbl->GetMethod(pclass, L"Rename", 0, 
>&pinput_params,
>+                                     NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
>+                                                &pclass_instance);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+
>+    VariantInit(&new_name);
>+    new_name.vt = VT_BSTR;
>+    new_name.bstrVal = wide_name;
>+    hres = pclass_instance->lpVtbl->Put(pclass_instance, L"NewName", 0,
>+                                        &new_name, 0);
>+    if (FAILED(hres)) {
>+        retval = false;
>+        goto error;
>+    }
>+    hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal, L"Rename", 0,
>+                                    pcontext, pclass_instance, NULL, 
>NULL);
>+    if (FAILED(hres)) {
>+        retval = false;
>+    }
>+
>+error:
>+    if (text_object_string != NULL) {
>+        SysFreeString(text_object_string);
>+        text_object_string = NULL;
>+    }
>+    if (psa != NULL) {
>+        SafeArrayDestroy(psa);
>+        psa = NULL;
>+    }
>+    if (ploc != NULL) {
>+        ploc->lpVtbl->Release(ploc);
>+        ploc = NULL;
>+    }
>+    if (pcontext != NULL) {
>+        pcontext->lpVtbl->Release(pcontext);
>+        pcontext = NULL;
>+    }
>+    if (psvc != NULL) {
>+        psvc->lpVtbl->Release(psvc);
>+        psvc = NULL;
>+    }
>+    if (penumerate != NULL) {
>+        penumerate->lpVtbl->Release(penumerate);
>+        penumerate = NULL;
>+    }
>+    if (default_settings_data != NULL) {
>+        default_settings_data->lpVtbl->Release(default_settings_data);
>+        default_settings_data = NULL;
>+    }
>+    if (default_system != NULL) {
>+        default_system->lpVtbl->Release(default_system);
>+        default_system = NULL;
>+    }
>+    if (pcls_obj != NULL) {
>+        pcls_obj->lpVtbl->Release(pcls_obj);
>+        pcls_obj = NULL;
>+    }
>+    if (pclass != NULL) {
>+        pclass->lpVtbl->Release(pclass);
>+        pclass = NULL;
>+    }
>+    if (pinput_params != NULL) {
>+        pinput_params->lpVtbl->Release(pinput_params);
>+        pinput_params = NULL;
>+    }
>+    if (pclass_instance != NULL) {
>+        pclass_instance->lpVtbl->Release(pclass_instance);
>+        pclass_instance = NULL;
>+    }
>+    if (text_object != NULL) {
>+        text_object->lpVtbl->Release(text_object);
>+        text_object = NULL;
>+    }
>+    if (pout_params != NULL) {
>+        pout_params->lpVtbl->Release(pout_params);
>+        pout_params = NULL;
>+    }
>+    if (wide_name != NULL) {
>+        free(wide_name);
>+        wide_name = NULL;
>+    }
>+    VariantClear(&vt_prop);
>+    VariantClear(&switch_setting_path);
>+
>+    if (!retval) {
>+        get_hres_error(hres);
>+    }
>+    CoUninitialize();
>+    return retval;
>+}
>diff --git a/lib/wmi.h b/lib/wmi.h
>new file mode 100644
>index 0000000..28910e7
>--- /dev/null
>+++ b/lib/wmi.h
>@@ -0,0 +1,51 @@
>+/*
>+ * Copyright (c) 2016 Cloudbase Solutions Srl
>+ *
>+ * Licensed under the Apache License, Version 2.0 (the "License");
>+ * you may not use this file except in compliance with the License.
>+ * You may obtain a copy of the License at
>+ *
>+ *     
>https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_license
>s_LICENSE-2D2.0&d=DgICAg&c=uilaK90D4TOVoH58JNXRgQ&r=Z6vowHUOjP5ysP_g372c49
>Nqc1vEKqHKNBkR5Q5Z7uo&m=bdxpwofizlzMhsYoOZoiq0yLJLSasRgmPwO00fUs_FY&s=wMJX
>-nHXxCR4etVk9vFL5012RjwlTwObSTej5EdAIj8&e= 
>+ *
>+ * Unless required by applicable law or agreed to in writing, software
>+ * distributed under the License is distributed on an "AS IS" BASIS,
>+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
>implied.
>+ * See the License for the specific language governing permissions and
>+ * limitations under the License.
>+ */
>+
>+#ifndef WMI_H
>+#define WMI_H 1
>+
>+#include <windefs.h>
>+#include <Wbemidl.h>
>+
>+static inline void fill_context(IWbemContext *pContext)
>+{
>+    VARIANT var;
>+
>+    /* IncludeQualifiers. */
>+    VariantInit(&var);
>+    var.vt = VT_BOOL;
>+    var.boolVal = VARIANT_TRUE;
>+    pContext->lpVtbl->SetValue(pContext, L"IncludeQualifiers", 0, &var);
>+    VariantClear(&var);
>+
>+    VariantInit(&var);
>+    var.vt = VT_I4;
>+    var.lVal = 0;
>+    pContext->lpVtbl->SetValue(pContext, L"PathLevel", 0, &var);
>+    VariantClear(&var);
>+
>+    /* ExcludeSystemProperties. */
>+    VariantInit(&var);
>+    var.vt = VT_BOOL;
>+    var.boolVal = VARIANT_FALSE;
>+    pContext->lpVtbl->SetValue(pContext, L"ExcludeSystemProperties", 0, 
>&var);
>+    VariantClear(&var);
>+}
>+
>+boolean create_wmi_port(char *name);
>+boolean delete_wmi_port(char *name);
>+
>+#endif /* wmi.h */
>-- 
>2.10.2.windows.1
>
>_______________________________________________
>dev mailing list
>dev at openvswitch.org
>https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_
>mailman_listinfo_ovs-2Ddev&d=DgICAg&c=uilaK90D4TOVoH58JNXRgQ&r=Z6vowHUOjP5
>ysP_g372c49Nqc1vEKqHKNBkR5Q5Z7uo&m=bdxpwofizlzMhsYoOZoiq0yLJLSasRgmPwO00fU
>s_FY&s=JM_StZiIrKaEqKV_MWk7SV-gvsyILF64dom-_br1dKk&e= 



More information about the dev mailing list