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
= xmalloc((strlen(name
) + 1) * sizeof(wchar_t));
411 if (!tranform_wide(name
, wide_name
)) {
415 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
417 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
419 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
422 WBEM_FLAG_FORWARD_ONLY
|
423 WBEM_FLAG_RETURN_IMMEDIATELY
,
432 /* Get the element path on the switch which will be deleted. */
433 if (!get_first_element(penumerate
, &pcls_obj
)) {
437 penumerate
->lpVtbl
->Release(penumerate
);
440 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
446 pcls_obj
->lpVtbl
->Release(pcls_obj
);
449 /* Get the class object and the parameters it can have. */
450 hres
= psvc
->lpVtbl
->GetObject(psvc
,
451 L
"Msvm_VirtualEthernetSwitchManagementService", 0, NULL
, &pcls_obj
,
459 hres
= pcls_obj
->lpVtbl
->GetMethod(pcls_obj
, L
"RemoveResourceSettings", 0,
460 &pinput_params
, NULL
);
466 pcls_obj
->lpVtbl
->Release(pcls_obj
);
469 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
478 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
485 VariantClear(&vt_prop
);
486 VariantInit(&vt_prop
);
487 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
488 variant_array
.parray
= psa
;
490 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings", 0,
497 /* Get the object of the Msvm_VirtualEthernetSwitchManagementService which
498 * we need to invoke the port deletion. */
499 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
502 L
"Msvm_VirtualEthernetSwitchManagementService",
503 WBEM_FLAG_FORWARD_ONLY
|
504 WBEM_FLAG_RETURN_IMMEDIATELY
,
513 if (!get_first_element(penumerate
, &pcls_obj
)) {
517 penumerate
->lpVtbl
->Release(penumerate
);
520 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
527 pcls_obj
->lpVtbl
->Release(pcls_obj
);
530 /* Invoke the delete port method. */
531 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
532 L
"RemoveResourceSettings", 0,
533 pcontext
, pclass_instance
, &pout_params
,
539 VariantClear(&vt_prop
);
540 VariantInit(&vt_prop
);
542 hres
= pout_params
->lpVtbl
->Get(pout_params
, L
"ReturnValue", 0,
550 unsigned int retvalue
= 0;
551 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
557 if (retvalue
!= 0 && retvalue
!= job_wait
) {
562 if (retvalue
== job_wait
) {
563 WCHAR job_path
[2048];
564 hres
= get_str_value(pout_params
, L
"Job", job_path
,
565 sizeof(job_path
) / sizeof(WCHAR
));
570 hres
= wait_for_job(psvc
, job_path
);
577 VariantClear(&vt_prop
);
579 if (pcontext
!= NULL
) {
580 pcontext
->lpVtbl
->Release(pcontext
);
584 SafeArrayDestroy(psa
);
587 if (pcls_obj
!= NULL
) {
588 pcls_obj
->lpVtbl
->Release(pcls_obj
);
591 if (wide_name
!= NULL
) {
596 get_hres_error(hres
);
598 if (pinput_params
!= NULL
) {
599 pinput_params
->lpVtbl
->Release(pinput_params
);
600 pinput_params
= NULL
;
602 if (pout_params
!= NULL
) {
603 pout_params
->lpVtbl
->Release(pout_params
);
607 psvc
->lpVtbl
->Release(psvc
);
611 ploc
->lpVtbl
->Release(ploc
);
614 if (pclass_instance
!= NULL
) {
615 pclass_instance
->lpVtbl
->Release(pclass_instance
);
616 pclass_instance
= NULL
;
618 if (penumerate
!= NULL
) {
619 penumerate
->lpVtbl
->Release(penumerate
);
628 /* This function will create an internal port on the switch given a given name
629 * executing the method AddResourceSettings as per documentation:
630 * https://msdn.microsoft.com/en-us/library/hh850019%28v=vs.85%29.aspx.
631 * It will verify if the port is already defined, in which case it will use
632 * the specific port, and if the forwarding extension "Open vSwitch Extension"
633 * is enabled and running only on a single switch.
634 * After the port is created and bound to the switch we will disable the
635 * created net adapter and rename it to match the OVS bridge name .*/
637 create_wmi_port(char *name
) {
639 boolean retval
= true;
641 BSTR text_object_string
= NULL
;
643 IWbemLocator
*ploc
= NULL
;
644 IWbemContext
*pcontext
= NULL
;
645 IWbemServices
*psvc
= NULL
;
646 IEnumWbemClassObject
*penumerate
= NULL
;
647 IWbemClassObject
*default_settings_data
= NULL
;
648 IWbemClassObject
*default_system
= NULL
;
649 IWbemClassObject
*pcls_obj
= NULL
;
650 IWbemClassObject
*pclass
= NULL
;
651 IWbemClassObject
*pinput_params
= NULL
;
652 IWbemClassObject
*pclass_instance
= NULL
;
653 IWbemObjectTextSrc
*text_object
= NULL
;
654 IWbemClassObject
*pout_params
= NULL
;
656 wchar_t *wide_name
= NULL
;
658 VARIANT switch_setting_path
;
660 SAFEARRAY
*psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
661 VARIANT variant_array
;
664 VariantInit(&vt_prop
);
665 VariantInit(&switch_setting_path
);
666 sanitize_port_name(name
);
669 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
674 if (!initialize_wmi(&ploc
, &pcontext
)) {
675 VLOG_WARN("Could not initialize DCOM");
680 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
682 VLOG_WARN("Could not connect and set security for virtualization");
687 /* Check if the element already exists on the switch. */
688 wchar_t internal_port_query
[WMI_QUERY_COUNT
] = L
"SELECT * FROM "
689 L
"Msvm_InternalEthernetPort WHERE ElementName = \"";
691 wide_name
= xmalloc((strlen(name
) + 1) * sizeof(wchar_t));
693 if (!tranform_wide(name
, wide_name
)) {
698 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
700 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
701 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
704 WBEM_FLAG_FORWARD_ONLY
|
705 WBEM_FLAG_RETURN_IMMEDIATELY
,
714 if (get_first_element(penumerate
, &pcls_obj
)) {
715 VLOG_WARN("Port with name: %s already defined on the switch", name
);
718 penumerate
->lpVtbl
->Release(penumerate
);
721 /* Check if the extension is enabled and running. Also check if the
722 * the extension is enabled on more than one switch. */
723 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
726 L
"FROM Msvm_EthernetSwitchExtension "
728 L
"ElementName=\"Open vSwitch Extension\" "
729 L
"AND EnabledState=2 "
730 L
"AND HealthState=5",
731 WBEM_FLAG_FORWARD_ONLY
|
732 WBEM_FLAG_RETURN_IMMEDIATELY
,
741 if (!get_first_element(penumerate
, &pcls_obj
)) {
742 VLOG_WARN("Open vSwitch Extension is not enabled on any switch");
746 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
747 L
"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name = \"");
749 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"SystemName", 0,
756 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
759 VariantClear(&vt_prop
);
760 pcls_obj
->lpVtbl
->Release(pcls_obj
);
763 if (get_first_element(penumerate
, &pcls_obj
)) {
764 VLOG_WARN("The extension is activated on more than one switch, "
765 "aborting operation. Please activate the extension on a "
770 penumerate
->lpVtbl
->Release(penumerate
);
772 if (pcls_obj
!= NULL
) {
773 pcls_obj
->lpVtbl
->Release(pcls_obj
);
777 /* Get the switch object on which the extension is activated. */
778 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
779 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
782 WBEM_FLAG_FORWARD_ONLY
|
783 WBEM_FLAG_RETURN_IMMEDIATELY
,
792 if (!get_first_element(penumerate
, &pcls_obj
)) {
793 VLOG_WARN("Could not get the switch object on which the extension is"
798 penumerate
->lpVtbl
->Release(penumerate
);
801 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"ElementName", 0, &vt_prop
, 0, 0);
808 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
809 L
"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData WHERE "
810 L
"ElementName = \"");
812 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
814 VariantClear(&vt_prop
);
816 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"Name", 0, &vt_prop
, 0, 0);
822 pcls_obj
->lpVtbl
->Release(pcls_obj
);
825 /* Should be enough to give the InstanceID, from msdn documentation:
826 * Uniquely identifies an instance of this class. This property is
827 * inherited from CIM_SettingData and is always
828 * set to "Microsoft:GUID\DeviceSpecificData". */
829 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
830 L
"\" AND InstanceID = \"Microsoft:");
831 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
833 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
836 VariantClear(&vt_prop
);
838 /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to the switch
839 * object on which the extension is activated. */
840 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
843 WBEM_FLAG_FORWARD_ONLY
|
844 WBEM_FLAG_RETURN_IMMEDIATELY
,
853 if (!get_first_element(penumerate
, &pcls_obj
)) {
854 VLOG_WARN("Could not get the first "
855 "Msvm_VirtualEthernetSwitchSettingData object");
859 penumerate
->lpVtbl
->Release(penumerate
);
862 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &switch_setting_path
,
869 pcls_obj
->lpVtbl
->Release(pcls_obj
);
872 /* Retrieve a default allocation port. This object will be later filled
873 * with optional data to create an switch internal port. */
874 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
877 L
"Msvm_EthernetPortAllocationSettingData "
878 L
"WHERE InstanceID LIKE '%%%%\\\\Default' "
879 L
"AND ResourceSubType = "
880 L
"'Microsoft:Hyper-V:Ethernet Connection'",
881 WBEM_FLAG_FORWARD_ONLY
|
882 WBEM_FLAG_RETURN_IMMEDIATELY
,
891 if (!get_first_element(penumerate
, &default_settings_data
)) {
892 VLOG_WARN("Could not retrieve default allocation port object");
896 penumerate
->lpVtbl
->Release(penumerate
);
899 /* Retrieve the default computer system on which the port allocation will
901 * Instead of querying using Description, we can query using InstallDate.
902 * From MSDN documentation regarding InstallDate:
903 * The date and time the virtual machine configuration was created for
904 * a virtual machine, or Null, for a management operating system. */
905 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
907 L
"SELECT * FROM Msvm_ComputerSystem WHERE "
908 L
"InstallDate is NULL",
909 WBEM_FLAG_FORWARD_ONLY
|
910 WBEM_FLAG_RETURN_IMMEDIATELY
,
919 if (!get_first_element(penumerate
, &default_system
)) {
920 VLOG_WARN("Could not retrieve default computer system object");
925 hres
= default_system
->lpVtbl
->Get(default_system
, L
"__PATH",
931 penumerate
->lpVtbl
->Release(penumerate
);
935 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
942 VariantClear(&vt_prop
);
943 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
944 variant_array
.parray
= psa
;
945 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
953 hres
= psvc
->lpVtbl
->GetObject(psvc
,
954 L
"Msvm_VirtualEthernetSwitchManagementService",
955 0, NULL
, &pclass
, NULL
);
961 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"AddResourceSettings", 0,
962 &pinput_params
, NULL
);
968 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
975 /* Store the switch setting path retrieved above in the affected
976 * configuration field of the class instance. */
977 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
,
978 L
"AffectedConfiguration", 0,
979 &switch_setting_path
, 0);
986 /* Store the port name in the ElementName field of the default allocation
988 vt_prop
.vt
= VT_BSTR
;
989 vt_prop
.bstrVal
= SysAllocString(wide_name
);
990 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
993 VariantClear(&vt_prop
);
999 /* Retrieve and store the serialized data of the modified default switch
1001 hres
= CoCreateInstance(&CLSID_WbemObjectTextSrc
,
1003 CLSCTX_INPROC_SERVER
,
1004 &IID_IWbemObjectTextSrc
,
1005 (void**)&text_object
);
1011 hres
= text_object
->lpVtbl
->GetText(text_object
, 0,
1012 default_settings_data
,
1013 WMI_OBJ_TEXT_WMI_DTD_2_0
,
1015 &text_object_string
);
1020 hres
= SafeArrayDestroy(psa
);
1022 VLOG_WARN("Could not clear the data of the array");
1027 psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
1030 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
1036 variant_array
.parray
= psa
;
1037 hres
= SafeArrayPutElement(psa
, count
, text_object_string
);
1042 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings",
1043 0, &variant_array
, 0);
1049 /* Get the object of the switch service. */
1050 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1053 L
"Msvm_VirtualEthernetSwitchManagementService",
1054 WBEM_FLAG_FORWARD_ONLY
|
1055 WBEM_FLAG_RETURN_IMMEDIATELY
,
1063 if (!get_first_element(penumerate
, &pcls_obj
)) {
1064 VLOG_WARN("Could not get the object of the switch service");
1068 penumerate
->lpVtbl
->Release(penumerate
);
1071 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1076 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1079 /* Try to add the port to the switch. */
1080 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
1081 L
"AddResourceSettings", 0,
1082 pcontext
, pclass_instance
, &pout_params
,
1089 unsigned int retvalue
= 0;
1090 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
1096 if (retvalue
!= 0 && retvalue
!= job_wait
) {
1101 if (retvalue
== job_wait
) {
1102 WCHAR job_path
[2048];
1103 hres
= get_str_value(pout_params
, L
"Job", job_path
,
1104 sizeof(job_path
) / sizeof(WCHAR
));
1109 hres
= wait_for_job(psvc
, job_path
);
1116 pclass
->lpVtbl
->Release(pclass
);
1118 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1119 pclass_instance
= NULL
;
1120 pinput_params
->lpVtbl
->Release(pinput_params
);
1121 pinput_params
= NULL
;
1122 psvc
->lpVtbl
->Release(psvc
);
1124 VariantClear(&vt_prop
);
1126 if (!connect_set_security(ploc
, pcontext
, L
"Root\\StandardCimv2",
1128 VLOG_WARN("Could not connect and set security for CIM");
1133 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
1134 L
"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
1135 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
1136 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"%%'");
1138 /* Get the object with the port name equal to name on the CIM. */
1139 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1141 internal_port_query
,
1142 WBEM_FLAG_FORWARD_ONLY
|
1143 WBEM_FLAG_RETURN_IMMEDIATELY
,
1147 if (!get_first_element(penumerate
, &pcls_obj
)) {
1148 VLOG_WARN("Element name: %s not found in CIM", name
);
1152 penumerate
->lpVtbl
->Release(penumerate
);
1154 pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1155 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1158 /* Disable the adapter with port name equal with name. */
1159 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Disable", 0,
1160 pcontext
, NULL
, NULL
, NULL
);
1167 hres
= psvc
->lpVtbl
->GetObject(psvc
, L
"MSFT_NetAdapter", 0, NULL
, &pclass
,
1174 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"Rename", 0, &pinput_params
,
1181 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
1188 VariantInit(&new_name
);
1189 new_name
.vt
= VT_BSTR
;
1190 new_name
.bstrVal
= wide_name
;
1191 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"NewName", 0,
1197 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Rename", 0,
1198 pcontext
, pclass_instance
, NULL
, NULL
);
1204 if (text_object_string
!= NULL
) {
1205 SysFreeString(text_object_string
);
1206 text_object_string
= NULL
;
1209 SafeArrayDestroy(psa
);
1213 ploc
->lpVtbl
->Release(ploc
);
1216 if (pcontext
!= NULL
) {
1217 pcontext
->lpVtbl
->Release(pcontext
);
1221 psvc
->lpVtbl
->Release(psvc
);
1224 if (penumerate
!= NULL
) {
1225 penumerate
->lpVtbl
->Release(penumerate
);
1228 if (default_settings_data
!= NULL
) {
1229 default_settings_data
->lpVtbl
->Release(default_settings_data
);
1230 default_settings_data
= NULL
;
1232 if (default_system
!= NULL
) {
1233 default_system
->lpVtbl
->Release(default_system
);
1234 default_system
= NULL
;
1236 if (pcls_obj
!= NULL
) {
1237 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1240 if (pclass
!= NULL
) {
1241 pclass
->lpVtbl
->Release(pclass
);
1244 if (pinput_params
!= NULL
) {
1245 pinput_params
->lpVtbl
->Release(pinput_params
);
1246 pinput_params
= NULL
;
1248 if (pclass_instance
!= NULL
) {
1249 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1250 pclass_instance
= NULL
;
1252 if (text_object
!= NULL
) {
1253 text_object
->lpVtbl
->Release(text_object
);
1256 if (pout_params
!= NULL
) {
1257 pout_params
->lpVtbl
->Release(pout_params
);
1260 if (wide_name
!= NULL
) {
1264 VariantClear(&vt_prop
);
1265 VariantClear(&switch_setting_path
);
1268 get_hres_error(hres
);