2 * Copyright (c) 2016 Cloudbase Solutions Srl
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include "openvswitch/vlog.h"
25 VLOG_DEFINE_THIS_MODULE(wmi
);
37 sanitize_port_name(char *name
)
43 if ((*p1
) == '\'' || (*p1
) == '\"') {
55 /* This function will output the appropriate message for a given HRESULT.*/
57 get_hres_error(HRESULT hres
)
59 char *error_msg
= NULL
;
61 if (FACILITY_WINDOWS
== HRESULT_FACILITY(hres
)) {
62 hres
= HRESULT_CODE(hres
);
65 VLOG_ERR("%s", ovs_format_message(hres
));
69 check_return_value(HRESULT hres
)
80 get_variant_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
87 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, field_name
, 0, value
, 0, 0);
96 /* This function retrieves the uint16_t value from a given class object with
97 * the field name field_name. */
99 get_uint16_t_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
103 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
104 *value
= V_UI2(&vt_prop
);
109 /* This function retrieves the unsigned int values from a given class object
110 * with the field name field_name. */
112 get_uint_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
116 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
117 *value
= V_UI4(&vt_prop
);
122 /* This function retrieves the unsigned short value from a given class object
123 * with the field name field_name. */
125 get_ushort_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
126 unsigned short *value
)
129 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
130 *value
= V_UI2(&vt_prop
);
135 /* This function retrieves the BSTR value from a given class object with
136 * the field name field_name, to a preallocated destination dest and with the
137 * maximum length max_dest_lgth. */
139 get_str_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
, wchar_t *dest
,
143 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
145 if (wcscpy_s(dest
, max_dest_lgth
, vt_prop
.bstrVal
)) {
146 VariantClear(&vt_prop
);
147 VLOG_WARN("get_str_value, wcscpy_s failed :%s", ovs_strerror(errno
));
148 return WBEM_E_FAILED
;
151 VariantClear(&vt_prop
);
155 /* This function waits for a WMI job to finish and retrieves the error code
156 * if the job failed */
158 wait_for_job(IWbemServices
*psvc
, wchar_t *job_path
)
160 IWbemClassObject
*pcls_obj
= NULL
;
162 uint16_t job_state
= 0;
166 if(!check_return_value(psvc
->lpVtbl
->GetObject(psvc
, job_path
, 0, NULL
,
168 retval
= WBEM_E_FAILED
;
172 retval
= get_uint16_t_value(pcls_obj
, L
"JobState", &job_state
);
173 if (FAILED(retval
)) {
177 if (job_state
== job_starting
|| job_state
== job_running
) {
179 } else if (job_state
== job_completed
) {
182 /* Error occurred. */
183 retval
= get_uint16_t_value(pcls_obj
, L
"ErrorCode", &error
);
184 if (FAILED(retval
)) {
187 VLOG_WARN("Job failed with error: %d", error
);
188 retval
= WBEM_E_FAILED
;;
192 if (pcls_obj
!= NULL
) {
193 pcls_obj
->lpVtbl
->Release(pcls_obj
);
198 if (pcls_obj
!= NULL
) {
199 pcls_obj
->lpVtbl
->Release(pcls_obj
);
206 /* This function will initialize DCOM retrieving the WMI locator's ploc and
207 * the context associated to it. */
209 initialize_wmi(IWbemLocator
**ploc
, IWbemContext
**pcontext
)
213 /* Initialize COM. */
214 hres
= CoInitialize(NULL
);
220 /* Initialize COM security. */
221 hres
= CoInitializeSecurity(NULL
,
225 RPC_C_AUTHN_LEVEL_DEFAULT
,
226 RPC_C_IMP_LEVEL_IMPERSONATE
,
236 hres
= CoCreateInstance(&CLSID_WbemContext
,
238 CLSCTX_INPROC_SERVER
,
246 fill_context(*pcontext
);
248 /* Initialize locator's (ploc) to WMI. */
249 hres
= CoCreateInstance(&CLSID_WbemLocator
,
251 CLSCTX_INPROC_SERVER
,
262 /* This function connects the WMI locator's ploc to a given WMI provider
263 * defined in server and also sets the required security levels for a local
264 * connection to it. */
266 connect_set_security(IWbemLocator
*ploc
, IWbemContext
*pcontext
,
267 wchar_t *server
, IWbemServices
**psvc
)
271 /* Connect to server. */
272 hres
= ploc
->lpVtbl
->ConnectServer(ploc
,
286 /* Set security levels. */
287 hres
= CoSetProxyBlanket((IUnknown
*) *psvc
,
291 RPC_C_AUTHN_LEVEL_CALL
,
292 RPC_C_IMP_LEVEL_IMPERSONATE
,
303 /* This function retrieves the first class object of a given enumeration
304 * outputted by a query and fails if it could not retrieve the object or there
305 * was no object to retrieve */
307 get_first_element(IEnumWbemClassObject
*penumerate
,
308 IWbemClassObject
**pcls_obj
)
310 unsigned long retval
= 0;
312 if (penumerate
== NULL
) {
313 VLOG_WARN("Enumeration Class Object is NULL. Cannot get the first"
318 HRESULT hres
= penumerate
->lpVtbl
->Next(penumerate
, WBEM_INFINITE
, 1,
322 if (!check_return_value(hres
) || retval
== 0) {
329 /* This function is a wrapper that transforms a char * into a wchar_t * */
331 tranform_wide(char *name
, wchar_t *wide_name
)
333 unsigned long size
= strlen(name
) + 1;
336 if (wide_name
== NULL
) {
337 VLOG_WARN("Provided wide string is NULL");
341 ret
= mbstowcs(wide_name
, name
, size
);
344 VLOG_WARN("Invalid multibyte character is encountered");
346 } else if (ret
== size
) {
347 VLOG_WARN("Returned wide string not NULL terminated");
354 #define WMI_QUERY_COUNT 2048
356 /* This function will delete a switch internal port with a given name as input
357 * executing "RemoveResourceSettings" as per documentation:
358 * https://msdn.microsoft.com/en-us/library/hh850277%28v=vs.85%29.aspx
359 * allocating the data and populating the needed fields to execute the
362 delete_wmi_port(char *name
)
365 boolean retval
= true;
367 IWbemLocator
*ploc
= NULL
;
368 IWbemServices
*psvc
= NULL
;
369 IWbemContext
*pcontext
= NULL
;
370 IWbemClassObject
*pclass_instance
= NULL
;
371 IWbemClassObject
*pinput_params
= NULL
;
372 IWbemClassObject
*pcls_obj
= NULL
;
373 IWbemClassObject
*pout_params
= NULL
;
374 IEnumWbemClassObject
*penumerate
= NULL
;
376 sanitize_port_name(name
);
378 VARIANT variant_array
;
379 wchar_t *wide_name
= NULL
;
380 VariantInit(&vt_prop
);
381 VariantInit(&variant_array
);
384 SAFEARRAY
* psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
386 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
391 if (!initialize_wmi(&ploc
, &pcontext
)) {
392 VLOG_WARN("Could not initialize DCOM");
397 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
399 VLOG_WARN("Could not connect and set security for virtualization");
405 /* Get the port with the element name equal to the name input. */
406 wchar_t internal_port_query
[WMI_QUERY_COUNT
] = L
"SELECT * from "
407 L
"Msvm_EthernetPortAllocationSettingData WHERE ElementName = \"" ;
409 wide_name
= malloc((strlen(name
) + 1) * sizeof(wchar_t));
410 if (wide_name
== NULL
) {
411 VLOG_WARN("Could not allocate memory for wide string");
416 if (!tranform_wide(name
, wide_name
)) {
420 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
422 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
424 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
427 WBEM_FLAG_FORWARD_ONLY
|
428 WBEM_FLAG_RETURN_IMMEDIATELY
,
437 /* Get the element path on the switch which will be deleted. */
438 if (!get_first_element(penumerate
, &pcls_obj
)) {
442 penumerate
->lpVtbl
->Release(penumerate
);
445 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
451 pcls_obj
->lpVtbl
->Release(pcls_obj
);
454 /* Get the class object and the parameters it can have. */
455 hres
= psvc
->lpVtbl
->GetObject(psvc
,
456 L
"Msvm_VirtualEthernetSwitchManagementService", 0, NULL
, &pcls_obj
,
464 hres
= pcls_obj
->lpVtbl
->GetMethod(pcls_obj
, L
"RemoveResourceSettings", 0,
465 &pinput_params
, NULL
);
471 pcls_obj
->lpVtbl
->Release(pcls_obj
);
474 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
483 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
490 VariantClear(&vt_prop
);
491 VariantInit(&vt_prop
);
492 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
493 variant_array
.parray
= psa
;
495 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings", 0,
502 /* Get the object of the Msvm_VirtualEthernetSwitchManagementService which
503 * we need to invoke the port deletion. */
504 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
507 L
"Msvm_VirtualEthernetSwitchManagementService",
508 WBEM_FLAG_FORWARD_ONLY
|
509 WBEM_FLAG_RETURN_IMMEDIATELY
,
518 if (!get_first_element(penumerate
, &pcls_obj
)) {
522 penumerate
->lpVtbl
->Release(penumerate
);
525 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
532 pcls_obj
->lpVtbl
->Release(pcls_obj
);
535 /* Invoke the delete port method. */
536 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
537 L
"RemoveResourceSettings", 0,
538 pcontext
, pclass_instance
, &pout_params
,
544 VariantClear(&vt_prop
);
545 VariantInit(&vt_prop
);
547 hres
= pout_params
->lpVtbl
->Get(pout_params
, L
"ReturnValue", 0,
555 unsigned int retvalue
= 0;
556 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
562 if (retvalue
!= 0 && retvalue
!= job_wait
) {
567 if (retvalue
== job_wait
) {
568 WCHAR job_path
[2048];
569 hres
= get_str_value(pout_params
, L
"Job", job_path
,
570 sizeof(job_path
) / sizeof(WCHAR
));
575 hres
= wait_for_job(psvc
, job_path
);
582 VariantClear(&vt_prop
);
584 if (pcontext
!= NULL
) {
585 pcontext
->lpVtbl
->Release(pcontext
);
589 SafeArrayDestroy(psa
);
592 if (pcls_obj
!= NULL
) {
593 pcls_obj
->lpVtbl
->Release(pcls_obj
);
596 if (wide_name
!= NULL
) {
601 get_hres_error(hres
);
603 if (pinput_params
!= NULL
) {
604 pinput_params
->lpVtbl
->Release(pinput_params
);
605 pinput_params
= NULL
;
607 if (pout_params
!= NULL
) {
608 pout_params
->lpVtbl
->Release(pout_params
);
612 psvc
->lpVtbl
->Release(psvc
);
616 ploc
->lpVtbl
->Release(ploc
);
619 if (pclass_instance
!= NULL
) {
620 pclass_instance
->lpVtbl
->Release(pclass_instance
);
621 pclass_instance
= NULL
;
623 if (penumerate
!= NULL
) {
624 penumerate
->lpVtbl
->Release(penumerate
);
633 /* This function will create an internal port on the switch given a given name
634 * executing the method AddResourceSettings as per documentation:
635 * https://msdn.microsoft.com/en-us/library/hh850019%28v=vs.85%29.aspx.
636 * It will verify if the port is already defined, in which case it will use
637 * the specific port, and if the forwarding extension "Open vSwitch Extension"
638 * is enabled and running only on a single switch.
639 * After the port is created and bound to the switch we will disable the
640 * created net adapter and rename it to match the OVS bridge name .*/
642 create_wmi_port(char *name
) {
644 boolean retval
= true;
646 BSTR text_object_string
= NULL
;
648 IWbemLocator
*ploc
= NULL
;
649 IWbemContext
*pcontext
= NULL
;
650 IWbemServices
*psvc
= NULL
;
651 IEnumWbemClassObject
*penumerate
= NULL
;
652 IWbemClassObject
*default_settings_data
= NULL
;
653 IWbemClassObject
*default_system
= NULL
;
654 IWbemClassObject
*pcls_obj
= NULL
;
655 IWbemClassObject
*pclass
= NULL
;
656 IWbemClassObject
*pinput_params
= NULL
;
657 IWbemClassObject
*pclass_instance
= NULL
;
658 IWbemObjectTextSrc
*text_object
= NULL
;
659 IWbemClassObject
*pout_params
= NULL
;
661 wchar_t *wide_name
= NULL
;
663 VARIANT switch_setting_path
;
665 SAFEARRAY
*psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
666 VARIANT variant_array
;
669 VariantInit(&vt_prop
);
670 VariantInit(&switch_setting_path
);
671 sanitize_port_name(name
);
674 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
679 if (!initialize_wmi(&ploc
, &pcontext
)) {
680 VLOG_WARN("Could not initialize DCOM");
685 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
687 VLOG_WARN("Could not connect and set security for virtualization");
692 /* Check if the element already exists on the switch. */
693 wchar_t internal_port_query
[WMI_QUERY_COUNT
] = L
"SELECT * FROM "
694 L
"Msvm_InternalEthernetPort WHERE ElementName = \"";
696 wide_name
= malloc((strlen(name
) + 1) * sizeof(wchar_t));
697 if (wide_name
== NULL
) {
698 VLOG_WARN("Could not allocate memory for wide string");
703 if (!tranform_wide(name
, wide_name
)) {
708 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
710 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
711 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
714 WBEM_FLAG_FORWARD_ONLY
|
715 WBEM_FLAG_RETURN_IMMEDIATELY
,
724 if (get_first_element(penumerate
, &pcls_obj
)) {
725 VLOG_WARN("Port with name: %s already defined on the switch", name
);
728 penumerate
->lpVtbl
->Release(penumerate
);
731 /* Check if the extension is enabled and running. Also check if the
732 * the extension is enabled on more than one switch. */
733 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
736 L
"FROM Msvm_EthernetSwitchExtension "
738 L
"ElementName=\"Open vSwitch Extension\" "
739 L
"AND EnabledState=2 "
740 L
"AND HealthState=5",
741 WBEM_FLAG_FORWARD_ONLY
|
742 WBEM_FLAG_RETURN_IMMEDIATELY
,
751 if (!get_first_element(penumerate
, &pcls_obj
)) {
752 VLOG_WARN("Open vSwitch Extension is not enabled on any switch");
756 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
757 L
"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name = \"");
759 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"SystemName", 0,
766 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
769 VariantClear(&vt_prop
);
770 pcls_obj
->lpVtbl
->Release(pcls_obj
);
773 if (get_first_element(penumerate
, &pcls_obj
)) {
774 VLOG_WARN("The extension is activated on more than one switch, "
775 "aborting operation. Please activate the extension on a "
780 penumerate
->lpVtbl
->Release(penumerate
);
782 if (pcls_obj
!= NULL
) {
783 pcls_obj
->lpVtbl
->Release(pcls_obj
);
787 /* Get the switch object on which the extension is activated. */
788 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
789 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
792 WBEM_FLAG_FORWARD_ONLY
|
793 WBEM_FLAG_RETURN_IMMEDIATELY
,
802 if (!get_first_element(penumerate
, &pcls_obj
)) {
803 VLOG_WARN("Could not get the switch object on which the extension is"
808 penumerate
->lpVtbl
->Release(penumerate
);
811 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"ElementName", 0, &vt_prop
, 0, 0);
818 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
819 L
"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData WHERE "
820 L
"ElementName = \"");
822 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
824 VariantClear(&vt_prop
);
826 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"Name", 0, &vt_prop
, 0, 0);
832 pcls_obj
->lpVtbl
->Release(pcls_obj
);
835 /* Should be enough to give the InstanceID, from msdn documentation:
836 * Uniquely identifies an instance of this class. This property is
837 * inherited from CIM_SettingData and is always
838 * set to "Microsoft:GUID\DeviceSpecificData". */
839 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
840 L
"\" AND InstanceID = \"Microsoft:");
841 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
843 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
846 VariantClear(&vt_prop
);
848 /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to the switch
849 * object on which the extension is activated. */
850 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
853 WBEM_FLAG_FORWARD_ONLY
|
854 WBEM_FLAG_RETURN_IMMEDIATELY
,
863 if (!get_first_element(penumerate
, &pcls_obj
)) {
864 VLOG_WARN("Could not get the first "
865 "Msvm_VirtualEthernetSwitchSettingData object");
869 penumerate
->lpVtbl
->Release(penumerate
);
872 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &switch_setting_path
,
879 pcls_obj
->lpVtbl
->Release(pcls_obj
);
882 /* Retrieve a default allocation port. This object will be later filled
883 * with optional data to create an switch internal port. */
884 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
887 L
"Msvm_EthernetPortAllocationSettingData "
888 L
"WHERE InstanceID LIKE '%%%%\\\\Default' "
889 L
"AND ResourceSubType = "
890 L
"'Microsoft:Hyper-V:Ethernet Connection'",
891 WBEM_FLAG_FORWARD_ONLY
|
892 WBEM_FLAG_RETURN_IMMEDIATELY
,
901 if (!get_first_element(penumerate
, &default_settings_data
)) {
902 VLOG_WARN("Could not retrieve default allocation port object");
906 penumerate
->lpVtbl
->Release(penumerate
);
909 /* Retrieve the default computer system on which the port allocation will
911 * Instead of querying using Description, we can query using InstallDate.
912 * From MSDN documentation regarding InstallDate:
913 * The date and time the virtual machine configuration was created for
914 * a virtual machine, or Null, for a management operating system. */
915 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
917 L
"SELECT * FROM Msvm_ComputerSystem WHERE "
918 L
"InstallDate is NULL",
919 WBEM_FLAG_FORWARD_ONLY
|
920 WBEM_FLAG_RETURN_IMMEDIATELY
,
929 if (!get_first_element(penumerate
, &default_system
)) {
930 VLOG_WARN("Could not retrieve default computer system object");
935 hres
= default_system
->lpVtbl
->Get(default_system
, L
"__PATH",
941 penumerate
->lpVtbl
->Release(penumerate
);
945 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
952 VariantClear(&vt_prop
);
953 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
954 variant_array
.parray
= psa
;
955 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
963 hres
= psvc
->lpVtbl
->GetObject(psvc
,
964 L
"Msvm_VirtualEthernetSwitchManagementService",
965 0, NULL
, &pclass
, NULL
);
971 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"AddResourceSettings", 0,
972 &pinput_params
, NULL
);
978 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
985 /* Store the switch setting path retrieved above in the affected
986 * configuration field of the class instance. */
987 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
,
988 L
"AffectedConfiguration", 0,
989 &switch_setting_path
, 0);
996 /* Store the port name in the ElementName field of the default allocation
998 vt_prop
.vt
= VT_BSTR
;
999 vt_prop
.bstrVal
= SysAllocString(wide_name
);
1000 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
1003 VariantClear(&vt_prop
);
1009 /* Retrieve and store the serialized data of the modified default switch
1011 hres
= CoCreateInstance(&CLSID_WbemObjectTextSrc
,
1013 CLSCTX_INPROC_SERVER
,
1014 &IID_IWbemObjectTextSrc
,
1015 (void**)&text_object
);
1021 hres
= text_object
->lpVtbl
->GetText(text_object
, 0,
1022 default_settings_data
,
1023 WMI_OBJ_TEXT_WMI_DTD_2_0
,
1025 &text_object_string
);
1030 hres
= SafeArrayDestroy(psa
);
1032 VLOG_WARN("Could not clear the data of the array");
1037 psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
1040 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
1046 variant_array
.parray
= psa
;
1047 hres
= SafeArrayPutElement(psa
, count
, text_object_string
);
1052 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings",
1053 0, &variant_array
, 0);
1059 /* Get the object of the switch service. */
1060 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1063 L
"Msvm_VirtualEthernetSwitchManagementService",
1064 WBEM_FLAG_FORWARD_ONLY
|
1065 WBEM_FLAG_RETURN_IMMEDIATELY
,
1073 if (!get_first_element(penumerate
, &pcls_obj
)) {
1074 VLOG_WARN("Could not get the object of the switch service");
1078 penumerate
->lpVtbl
->Release(penumerate
);
1081 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1086 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1089 /* Try to add the port to the switch. */
1090 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
1091 L
"AddResourceSettings", 0,
1092 pcontext
, pclass_instance
, &pout_params
,
1099 unsigned int retvalue
= 0;
1100 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
1106 if (retvalue
!= 0 && retvalue
!= job_wait
) {
1111 if (retvalue
== job_wait
) {
1112 WCHAR job_path
[2048];
1113 hres
= get_str_value(pout_params
, L
"Job", job_path
,
1114 sizeof(job_path
) / sizeof(WCHAR
));
1119 hres
= wait_for_job(psvc
, job_path
);
1126 pclass
->lpVtbl
->Release(pclass
);
1128 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1129 pclass_instance
= NULL
;
1130 pinput_params
->lpVtbl
->Release(pinput_params
);
1131 pinput_params
= NULL
;
1132 psvc
->lpVtbl
->Release(psvc
);
1134 VariantClear(&vt_prop
);
1136 if (!connect_set_security(ploc
, pcontext
, L
"Root\\StandardCimv2",
1138 VLOG_WARN("Could not connect and set security for CIM");
1143 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
1144 L
"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
1145 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
1146 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"%%'");
1148 /* Get the object with the port name equal to name on the CIM. */
1149 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1151 internal_port_query
,
1152 WBEM_FLAG_FORWARD_ONLY
|
1153 WBEM_FLAG_RETURN_IMMEDIATELY
,
1157 if (!get_first_element(penumerate
, &pcls_obj
)) {
1158 VLOG_WARN("Element name: %s not found in CIM", name
);
1162 penumerate
->lpVtbl
->Release(penumerate
);
1164 pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1165 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1168 /* Disable the adapter with port name equal with name. */
1169 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Disable", 0,
1170 pcontext
, NULL
, NULL
, NULL
);
1177 hres
= psvc
->lpVtbl
->GetObject(psvc
, L
"MSFT_NetAdapter", 0, NULL
, &pclass
,
1184 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"Rename", 0, &pinput_params
,
1191 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
1198 VariantInit(&new_name
);
1199 new_name
.vt
= VT_BSTR
;
1200 new_name
.bstrVal
= wide_name
;
1201 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"NewName", 0,
1207 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Rename", 0,
1208 pcontext
, pclass_instance
, NULL
, NULL
);
1214 if (text_object_string
!= NULL
) {
1215 SysFreeString(text_object_string
);
1216 text_object_string
= NULL
;
1219 SafeArrayDestroy(psa
);
1223 ploc
->lpVtbl
->Release(ploc
);
1226 if (pcontext
!= NULL
) {
1227 pcontext
->lpVtbl
->Release(pcontext
);
1231 psvc
->lpVtbl
->Release(psvc
);
1234 if (penumerate
!= NULL
) {
1235 penumerate
->lpVtbl
->Release(penumerate
);
1238 if (default_settings_data
!= NULL
) {
1239 default_settings_data
->lpVtbl
->Release(default_settings_data
);
1240 default_settings_data
= NULL
;
1242 if (default_system
!= NULL
) {
1243 default_system
->lpVtbl
->Release(default_system
);
1244 default_system
= NULL
;
1246 if (pcls_obj
!= NULL
) {
1247 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1250 if (pclass
!= NULL
) {
1251 pclass
->lpVtbl
->Release(pclass
);
1254 if (pinput_params
!= NULL
) {
1255 pinput_params
->lpVtbl
->Release(pinput_params
);
1256 pinput_params
= NULL
;
1258 if (pclass_instance
!= NULL
) {
1259 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1260 pclass_instance
= NULL
;
1262 if (text_object
!= NULL
) {
1263 text_object
->lpVtbl
->Release(text_object
);
1266 if (pout_params
!= NULL
) {
1267 pout_params
->lpVtbl
->Release(pout_params
);
1270 if (wide_name
!= NULL
) {
1274 VariantClear(&vt_prop
);
1275 VariantClear(&switch_setting_path
);
1278 get_hres_error(hres
);