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"
24 VLOG_DEFINE_THIS_MODULE(wmi
);
36 sanitize_port_name(char *name
)
42 if ((*p1
) == '\'' || (*p1
) == '\"') {
54 /* This function will output the appropriate message for a given HRESULT.*/
56 get_hres_error(HRESULT hres
)
58 char *error_msg
= NULL
;
60 if (FACILITY_WINDOWS
== HRESULT_FACILITY(hres
)) {
61 hres
= HRESULT_CODE(hres
);
64 VLOG_ERR("%s", ovs_format_message(hres
));
68 check_return_value(HRESULT hres
)
79 get_variant_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
86 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, field_name
, 0, value
, 0, 0);
95 /* This function retrieves the uint16_t value from a given class object with
96 * the field name field_name. */
98 get_uint16_t_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
102 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
103 *value
= V_UI2(&vt_prop
);
108 /* This function retrieves the unsigned int values from a given class object
109 * with the field name field_name. */
111 get_uint_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
115 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
116 *value
= V_UI4(&vt_prop
);
121 /* This function retrieves the unsigned short value from a given class object
122 * with the field name field_name. */
124 get_ushort_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
,
125 unsigned short *value
)
128 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
129 *value
= V_UI2(&vt_prop
);
134 /* This function retrieves the BSTR value from a given class object with
135 * the field name field_name, to a preallocated destination dest and with the
136 * maximum length max_dest_lgth. */
138 get_str_value(IWbemClassObject
*pcls_obj
, wchar_t *field_name
, wchar_t *dest
,
142 HRESULT hres
= get_variant_value(pcls_obj
, field_name
, &vt_prop
);
144 if (wcscpy_s(dest
, max_dest_lgth
, vt_prop
.bstrVal
)) {
145 VariantClear(&vt_prop
);
146 VLOG_WARN("get_str_value, wcscpy_s failed :%s", ovs_strerror(errno
));
147 return WBEM_E_FAILED
;
150 VariantClear(&vt_prop
);
154 /* This function waits for a WMI job to finish and retrieves the error code
155 * if the job failed */
157 wait_for_job(IWbemServices
*psvc
, wchar_t *job_path
)
159 IWbemClassObject
*pcls_obj
= NULL
;
161 uint16_t job_state
= 0;
165 if(!check_return_value(psvc
->lpVtbl
->GetObject(psvc
, job_path
, 0, NULL
,
167 retval
= WBEM_E_FAILED
;
171 retval
= get_uint16_t_value(pcls_obj
, L
"JobState", &job_state
);
172 if (FAILED(retval
)) {
176 if (job_state
== job_starting
|| job_state
== job_running
) {
178 } else if (job_state
== job_completed
) {
181 /* Error occurred. */
182 retval
= get_uint16_t_value(pcls_obj
, L
"ErrorCode", &error
);
183 if (FAILED(retval
)) {
186 VLOG_WARN("Job failed with error: %d", error
);
187 retval
= WBEM_E_FAILED
;;
191 if (pcls_obj
!= NULL
) {
192 pcls_obj
->lpVtbl
->Release(pcls_obj
);
197 if (pcls_obj
!= NULL
) {
198 pcls_obj
->lpVtbl
->Release(pcls_obj
);
205 /* This function will initialize DCOM retrieving the WMI locator's ploc and
206 * the context associated to it. */
208 initialize_wmi(IWbemLocator
**ploc
, IWbemContext
**pcontext
)
212 /* Initialize COM. */
213 hres
= CoInitialize(NULL
);
219 /* Initialize COM security. */
220 hres
= CoInitializeSecurity(NULL
,
224 RPC_C_AUTHN_LEVEL_DEFAULT
,
225 RPC_C_IMP_LEVEL_IMPERSONATE
,
235 hres
= CoCreateInstance(&CLSID_WbemContext
,
237 CLSCTX_INPROC_SERVER
,
245 fill_context(*pcontext
);
247 /* Initialize locator's (ploc) to WMI. */
248 hres
= CoCreateInstance(&CLSID_WbemLocator
,
250 CLSCTX_INPROC_SERVER
,
261 /* This function connects the WMI locator's ploc to a given WMI provider
262 * defined in server and also sets the required security levels for a local
263 * connection to it. */
265 connect_set_security(IWbemLocator
*ploc
, IWbemContext
*pcontext
,
266 wchar_t *server
, IWbemServices
**psvc
)
270 /* Connect to server. */
271 hres
= ploc
->lpVtbl
->ConnectServer(ploc
,
285 /* Set security levels. */
286 hres
= CoSetProxyBlanket((IUnknown
*) *psvc
,
290 RPC_C_AUTHN_LEVEL_CALL
,
291 RPC_C_IMP_LEVEL_IMPERSONATE
,
302 /* This function retrieves the first class object of a given enumeration
303 * outputted by a query and fails if it could not retrieve the object or there
304 * was no object to retrieve */
306 get_first_element(IEnumWbemClassObject
*penumerate
,
307 IWbemClassObject
**pcls_obj
)
309 unsigned long retval
= 0;
311 if (penumerate
== NULL
) {
312 VLOG_WARN("Enumeration Class Object is NULL. Cannot get the first"
317 HRESULT hres
= penumerate
->lpVtbl
->Next(penumerate
, WBEM_INFINITE
, 1,
321 if (!check_return_value(hres
) || retval
== 0) {
328 /* This function is a wrapper that transforms a char * into a wchar_t * */
330 tranform_wide(char *name
, wchar_t *wide_name
)
332 unsigned long size
= strlen(name
) + 1;
335 if (wide_name
== NULL
) {
336 VLOG_WARN("Provided wide string is NULL");
340 ret
= mbstowcs(wide_name
, name
, size
);
343 VLOG_WARN("Invalid multibyte character is encountered");
345 } else if (ret
== size
) {
346 VLOG_WARN("Returned wide string not NULL terminated");
353 #define WMI_QUERY_COUNT 2048
355 /* This function will delete a switch internal port with a given name as input
356 * executing "RemoveResourceSettings" as per documentation:
357 * https://msdn.microsoft.com/en-us/library/hh850277%28v=vs.85%29.aspx
358 * allocating the data and populating the needed fields to execute the
361 delete_wmi_port(char *name
)
364 boolean retval
= true;
366 IWbemLocator
*ploc
= NULL
;
367 IWbemServices
*psvc
= NULL
;
368 IWbemContext
*pcontext
= NULL
;
369 IWbemClassObject
*pclass_instance
= NULL
;
370 IWbemClassObject
*pinput_params
= NULL
;
371 IWbemClassObject
*pcls_obj
= NULL
;
372 IWbemClassObject
*pout_params
= NULL
;
373 IEnumWbemClassObject
*penumerate
= NULL
;
375 sanitize_port_name(name
);
377 VARIANT variant_array
;
378 wchar_t *wide_name
= NULL
;
379 VariantInit(&vt_prop
);
380 VariantInit(&variant_array
);
383 SAFEARRAY
* psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
385 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
390 if (!initialize_wmi(&ploc
, &pcontext
)) {
391 VLOG_WARN("Could not initialize DCOM");
396 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
398 VLOG_WARN("Could not connect and set security for virtualization");
404 /* Get the port with the element name equal to the name input. */
405 wchar_t internal_port_query
[WMI_QUERY_COUNT
] = L
"SELECT * from "
406 L
"Msvm_EthernetPortAllocationSettingData WHERE ElementName = \"" ;
408 wide_name
= malloc((strlen(name
) + 1) * sizeof(wchar_t));
409 if (wide_name
== NULL
) {
410 VLOG_WARN("Could not allocate memory for wide string");
415 if (!tranform_wide(name
, wide_name
)) {
419 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
421 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
423 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
426 WBEM_FLAG_FORWARD_ONLY
|
427 WBEM_FLAG_RETURN_IMMEDIATELY
,
436 /* Get the element path on the switch which will be deleted. */
437 if (!get_first_element(penumerate
, &pcls_obj
)) {
441 penumerate
->lpVtbl
->Release(penumerate
);
444 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
450 pcls_obj
->lpVtbl
->Release(pcls_obj
);
453 /* Get the class object and the parameters it can have. */
454 hres
= psvc
->lpVtbl
->GetObject(psvc
,
455 L
"Msvm_VirtualEthernetSwitchManagementService", 0, NULL
, &pcls_obj
,
463 hres
= pcls_obj
->lpVtbl
->GetMethod(pcls_obj
, L
"RemoveResourceSettings", 0,
464 &pinput_params
, NULL
);
470 pcls_obj
->lpVtbl
->Release(pcls_obj
);
473 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
482 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
489 VariantClear(&vt_prop
);
490 VariantInit(&vt_prop
);
491 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
492 variant_array
.parray
= psa
;
494 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings", 0,
501 /* Get the object of the Msvm_VirtualEthernetSwitchManagementService which
502 * we need to invoke the port deletion. */
503 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
506 L
"Msvm_VirtualEthernetSwitchManagementService",
507 WBEM_FLAG_FORWARD_ONLY
|
508 WBEM_FLAG_RETURN_IMMEDIATELY
,
517 if (!get_first_element(penumerate
, &pcls_obj
)) {
521 penumerate
->lpVtbl
->Release(penumerate
);
524 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
531 pcls_obj
->lpVtbl
->Release(pcls_obj
);
534 /* Invoke the delete port method. */
535 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
536 L
"RemoveResourceSettings", 0,
537 pcontext
, pclass_instance
, &pout_params
,
543 VariantClear(&vt_prop
);
544 VariantInit(&vt_prop
);
546 hres
= pout_params
->lpVtbl
->Get(pout_params
, L
"ReturnValue", 0,
554 unsigned int retvalue
= 0;
555 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
561 if (retvalue
!= 0 && retvalue
!= job_wait
) {
566 if (retvalue
== job_wait
) {
567 WCHAR job_path
[2048];
568 hres
= get_str_value(pout_params
, L
"Job", job_path
,
569 sizeof(job_path
) / sizeof(WCHAR
));
574 hres
= wait_for_job(psvc
, job_path
);
581 VariantClear(&vt_prop
);
583 if (pcontext
!= NULL
) {
584 pcontext
->lpVtbl
->Release(pcontext
);
588 SafeArrayDestroy(psa
);
591 if (pcls_obj
!= NULL
) {
592 pcls_obj
->lpVtbl
->Release(pcls_obj
);
595 if (wide_name
!= NULL
) {
600 get_hres_error(hres
);
602 if (pinput_params
!= NULL
) {
603 pinput_params
->lpVtbl
->Release(pinput_params
);
604 pinput_params
= NULL
;
606 if (pout_params
!= NULL
) {
607 pout_params
->lpVtbl
->Release(pout_params
);
611 psvc
->lpVtbl
->Release(psvc
);
615 ploc
->lpVtbl
->Release(ploc
);
618 if (pclass_instance
!= NULL
) {
619 pclass_instance
->lpVtbl
->Release(pclass_instance
);
620 pclass_instance
= NULL
;
622 if (penumerate
!= NULL
) {
623 penumerate
->lpVtbl
->Release(penumerate
);
632 /* This function will create an internal port on the switch given a given name
633 * executing the method AddResourceSettings as per documentation:
634 * https://msdn.microsoft.com/en-us/library/hh850019%28v=vs.85%29.aspx.
635 * It will verify if the port is already defined, in which case it will use
636 * the specific port, and if the forwarding extension "Open vSwitch Extension"
637 * is enabled and running only on a single switch.
638 * After the port is created and bound to the switch we will disable the
639 * created net adapter and rename it to match the OVS bridge name .*/
641 create_wmi_port(char *name
) {
643 boolean retval
= true;
645 BSTR text_object_string
= NULL
;
647 IWbemLocator
*ploc
= NULL
;
648 IWbemContext
*pcontext
= NULL
;
649 IWbemServices
*psvc
= NULL
;
650 IEnumWbemClassObject
*penumerate
= NULL
;
651 IWbemClassObject
*default_settings_data
= NULL
;
652 IWbemClassObject
*default_system
= NULL
;
653 IWbemClassObject
*pcls_obj
= NULL
;
654 IWbemClassObject
*pclass
= NULL
;
655 IWbemClassObject
*pinput_params
= NULL
;
656 IWbemClassObject
*pclass_instance
= NULL
;
657 IWbemObjectTextSrc
*text_object
= NULL
;
658 IWbemClassObject
*pout_params
= NULL
;
660 wchar_t *wide_name
= NULL
;
662 VARIANT switch_setting_path
;
664 SAFEARRAY
*psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
665 VARIANT variant_array
;
668 VariantInit(&vt_prop
);
669 VariantInit(&switch_setting_path
);
670 sanitize_port_name(name
);
673 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
678 if (!initialize_wmi(&ploc
, &pcontext
)) {
679 VLOG_WARN("Could not initialize DCOM");
684 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
686 VLOG_WARN("Could not connect and set security for virtualization");
691 /* Check if the element already exists on the switch. */
692 wchar_t internal_port_query
[WMI_QUERY_COUNT
] = L
"SELECT * FROM "
693 L
"Msvm_InternalEthernetPort WHERE ElementName = \"";
695 wide_name
= malloc((strlen(name
) + 1) * sizeof(wchar_t));
696 if (wide_name
== NULL
) {
697 VLOG_WARN("Could not allocate memory for wide string");
702 if (!tranform_wide(name
, wide_name
)) {
707 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
709 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
710 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
713 WBEM_FLAG_FORWARD_ONLY
|
714 WBEM_FLAG_RETURN_IMMEDIATELY
,
723 if (get_first_element(penumerate
, &pcls_obj
)) {
724 VLOG_WARN("Port with name: %s already defined on the switch", name
);
727 penumerate
->lpVtbl
->Release(penumerate
);
730 /* Check if the extension is enabled and running. Also check if the
731 * the extension is enabled on more than one switch. */
732 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
735 L
"FROM Msvm_EthernetSwitchExtension "
737 L
"ElementName=\"Open vSwitch Extension\" "
738 L
"AND EnabledState=2 "
739 L
"AND HealthState=5",
740 WBEM_FLAG_FORWARD_ONLY
|
741 WBEM_FLAG_RETURN_IMMEDIATELY
,
750 if (!get_first_element(penumerate
, &pcls_obj
)) {
751 VLOG_WARN("Open vSwitch Extension is not enabled on any switch");
755 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
756 L
"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name = \"");
758 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"SystemName", 0,
765 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
768 VariantClear(&vt_prop
);
769 pcls_obj
->lpVtbl
->Release(pcls_obj
);
772 if (get_first_element(penumerate
, &pcls_obj
)) {
773 VLOG_WARN("The extension is activated on more than one switch, "
774 "aborting operation. Please activate the extension on a "
779 penumerate
->lpVtbl
->Release(penumerate
);
781 if (pcls_obj
!= NULL
) {
782 pcls_obj
->lpVtbl
->Release(pcls_obj
);
786 /* Get the switch object on which the extension is activated. */
787 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"\"");
788 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
791 WBEM_FLAG_FORWARD_ONLY
|
792 WBEM_FLAG_RETURN_IMMEDIATELY
,
801 if (!get_first_element(penumerate
, &pcls_obj
)) {
802 VLOG_WARN("Could not get the switch object on which the extension is"
807 penumerate
->lpVtbl
->Release(penumerate
);
810 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"ElementName", 0, &vt_prop
, 0, 0);
817 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
818 L
"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData WHERE "
819 L
"ElementName = \"");
821 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
823 VariantClear(&vt_prop
);
825 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"Name", 0, &vt_prop
, 0, 0);
831 pcls_obj
->lpVtbl
->Release(pcls_obj
);
834 /* Should be enough to give the InstanceID, from msdn documentation:
835 * Uniquely identifies an instance of this class. This property is
836 * inherited from CIM_SettingData and is always
837 * set to "Microsoft:GUID\DeviceSpecificData". */
838 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
839 L
"\" AND InstanceID = \"Microsoft:");
840 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
842 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
,
845 VariantClear(&vt_prop
);
847 /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to the switch
848 * object on which the extension is activated. */
849 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
852 WBEM_FLAG_FORWARD_ONLY
|
853 WBEM_FLAG_RETURN_IMMEDIATELY
,
862 if (!get_first_element(penumerate
, &pcls_obj
)) {
863 VLOG_WARN("Could not get the first "
864 "Msvm_VirtualEthernetSwitchSettingData object");
868 penumerate
->lpVtbl
->Release(penumerate
);
871 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &switch_setting_path
,
878 pcls_obj
->lpVtbl
->Release(pcls_obj
);
881 /* Retrieve a default allocation port. This object will be later filled
882 * with optional data to create an switch internal port. */
883 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
886 L
"Msvm_EthernetPortAllocationSettingData "
887 L
"WHERE InstanceID LIKE '%%%%\\\\Default' "
888 L
"AND ResourceSubType = "
889 L
"'Microsoft:Hyper-V:Ethernet Connection'",
890 WBEM_FLAG_FORWARD_ONLY
|
891 WBEM_FLAG_RETURN_IMMEDIATELY
,
900 if (!get_first_element(penumerate
, &default_settings_data
)) {
901 VLOG_WARN("Could not retrieve default allocation port object");
905 penumerate
->lpVtbl
->Release(penumerate
);
908 /* Retrieve the default computer system on which the port allocation will
910 * Instead of querying using Description, we can query using InstallDate.
911 * From MSDN documentation regarding InstallDate:
912 * The date and time the virtual machine configuration was created for
913 * a virtual machine, or Null, for a management operating system. */
914 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
916 L
"SELECT * FROM Msvm_ComputerSystem WHERE "
917 L
"InstallDate is NULL",
918 WBEM_FLAG_FORWARD_ONLY
|
919 WBEM_FLAG_RETURN_IMMEDIATELY
,
928 if (!get_first_element(penumerate
, &default_system
)) {
929 VLOG_WARN("Could not retrieve default computer system object");
934 hres
= default_system
->lpVtbl
->Get(default_system
, L
"__PATH",
940 penumerate
->lpVtbl
->Release(penumerate
);
944 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
951 VariantClear(&vt_prop
);
952 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
953 variant_array
.parray
= psa
;
954 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
962 hres
= psvc
->lpVtbl
->GetObject(psvc
,
963 L
"Msvm_VirtualEthernetSwitchManagementService",
964 0, NULL
, &pclass
, NULL
);
970 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"AddResourceSettings", 0,
971 &pinput_params
, NULL
);
977 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
984 /* Store the switch setting path retrieved above in the affected
985 * configuration field of the class instance. */
986 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
,
987 L
"AffectedConfiguration", 0,
988 &switch_setting_path
, 0);
995 /* Store the port name in the ElementName field of the default allocation
997 vt_prop
.vt
= VT_BSTR
;
998 vt_prop
.bstrVal
= SysAllocString(wide_name
);
999 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
1002 VariantClear(&vt_prop
);
1008 /* Retrieve and store the serialized data of the modified default switch
1010 hres
= CoCreateInstance(&CLSID_WbemObjectTextSrc
,
1012 CLSCTX_INPROC_SERVER
,
1013 &IID_IWbemObjectTextSrc
,
1014 (void**)&text_object
);
1020 hres
= text_object
->lpVtbl
->GetText(text_object
, 0,
1021 default_settings_data
,
1022 WMI_OBJ_TEXT_WMI_DTD_2_0
,
1024 &text_object_string
);
1029 hres
= SafeArrayDestroy(psa
);
1031 VLOG_WARN("Could not clear the data of the array");
1036 psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
1039 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
1045 variant_array
.parray
= psa
;
1046 hres
= SafeArrayPutElement(psa
, count
, text_object_string
);
1051 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings",
1052 0, &variant_array
, 0);
1058 /* Get the object of the switch service. */
1059 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1062 L
"Msvm_VirtualEthernetSwitchManagementService",
1063 WBEM_FLAG_FORWARD_ONLY
|
1064 WBEM_FLAG_RETURN_IMMEDIATELY
,
1072 if (!get_first_element(penumerate
, &pcls_obj
)) {
1073 VLOG_WARN("Could not get the object of the switch service");
1077 penumerate
->lpVtbl
->Release(penumerate
);
1080 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1085 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1088 /* Try to add the port to the switch. */
1089 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
1090 L
"AddResourceSettings", 0,
1091 pcontext
, pclass_instance
, &pout_params
,
1098 unsigned int retvalue
= 0;
1099 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
1105 if (retvalue
!= 0 && retvalue
!= job_wait
) {
1110 if (retvalue
== job_wait
) {
1111 WCHAR job_path
[2048];
1112 hres
= get_str_value(pout_params
, L
"Job", job_path
,
1113 sizeof(job_path
) / sizeof(WCHAR
));
1118 hres
= wait_for_job(psvc
, job_path
);
1125 pclass
->lpVtbl
->Release(pclass
);
1127 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1128 pclass_instance
= NULL
;
1129 pinput_params
->lpVtbl
->Release(pinput_params
);
1130 pinput_params
= NULL
;
1131 psvc
->lpVtbl
->Release(psvc
);
1133 VariantClear(&vt_prop
);
1135 if (!connect_set_security(ploc
, pcontext
, L
"Root\\StandardCimv2",
1137 VLOG_WARN("Could not connect and set security for CIM");
1142 wcscpy_s(internal_port_query
, WMI_QUERY_COUNT
,
1143 L
"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
1144 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, wide_name
);
1145 wcscat_s(internal_port_query
, WMI_QUERY_COUNT
, L
"%%'");
1147 /* Get the object with the port name equal to name on the CIM. */
1148 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1150 internal_port_query
,
1151 WBEM_FLAG_FORWARD_ONLY
|
1152 WBEM_FLAG_RETURN_IMMEDIATELY
,
1156 if (!get_first_element(penumerate
, &pcls_obj
)) {
1157 VLOG_WARN("Element name: %s not found in CIM", name
);
1161 penumerate
->lpVtbl
->Release(penumerate
);
1163 pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1164 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1167 /* Disable the adapter with port name equal with name. */
1168 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Disable", 0,
1169 pcontext
, NULL
, NULL
, NULL
);
1176 hres
= psvc
->lpVtbl
->GetObject(psvc
, L
"MSFT_NetAdapter", 0, NULL
, &pclass
,
1183 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"Rename", 0, &pinput_params
,
1190 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
1197 VariantInit(&new_name
);
1198 new_name
.vt
= VT_BSTR
;
1199 new_name
.bstrVal
= wide_name
;
1200 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"NewName", 0,
1206 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Rename", 0,
1207 pcontext
, pclass_instance
, NULL
, NULL
);
1213 if (text_object_string
!= NULL
) {
1214 SysFreeString(text_object_string
);
1215 text_object_string
= NULL
;
1218 SafeArrayDestroy(psa
);
1222 ploc
->lpVtbl
->Release(ploc
);
1225 if (pcontext
!= NULL
) {
1226 pcontext
->lpVtbl
->Release(pcontext
);
1230 psvc
->lpVtbl
->Release(psvc
);
1233 if (penumerate
!= NULL
) {
1234 penumerate
->lpVtbl
->Release(penumerate
);
1237 if (default_settings_data
!= NULL
) {
1238 default_settings_data
->lpVtbl
->Release(default_settings_data
);
1239 default_settings_data
= NULL
;
1241 if (default_system
!= NULL
) {
1242 default_system
->lpVtbl
->Release(default_system
);
1243 default_system
= NULL
;
1245 if (pcls_obj
!= NULL
) {
1246 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1249 if (pclass
!= NULL
) {
1250 pclass
->lpVtbl
->Release(pclass
);
1253 if (pinput_params
!= NULL
) {
1254 pinput_params
->lpVtbl
->Release(pinput_params
);
1255 pinput_params
= NULL
;
1257 if (pclass_instance
!= NULL
) {
1258 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1259 pclass_instance
= NULL
;
1261 if (text_object
!= NULL
) {
1262 text_object
->lpVtbl
->Release(text_object
);
1265 if (pout_params
!= NULL
) {
1266 pout_params
->lpVtbl
->Release(pout_params
);
1269 if (wide_name
!= NULL
) {
1273 VariantClear(&vt_prop
);
1274 VariantClear(&switch_setting_path
);
1277 get_hres_error(hres
);