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 /* This function will delete a switch internal port with a given name as input
354 * executing "RemoveResourceSettings" as per documentation:
355 * https://msdn.microsoft.com/en-us/library/hh850277%28v=vs.85%29.aspx
356 * allocating the data and populating the needed fields to execute the
359 delete_wmi_port(char *name
)
362 boolean retval
= true;
364 IWbemLocator
*ploc
= NULL
;
365 IWbemServices
*psvc
= NULL
;
366 IWbemContext
*pcontext
= NULL
;
367 IWbemClassObject
*pclass_instance
= NULL
;
368 IWbemClassObject
*pinput_params
= NULL
;
369 IWbemClassObject
*pcls_obj
= NULL
;
370 IWbemClassObject
*pout_params
= NULL
;
371 IEnumWbemClassObject
*penumerate
= NULL
;
373 sanitize_port_name(name
);
375 VARIANT variant_array
;
376 wchar_t *wide_name
= NULL
;
377 VariantInit(&vt_prop
);
378 VariantInit(&variant_array
);
381 SAFEARRAY
* psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
383 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
388 if (!initialize_wmi(&ploc
, &pcontext
)) {
389 VLOG_WARN("Could not initialize DCOM");
394 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
396 VLOG_WARN("Could not connect and set security for virtualization");
402 /* Get the port with the element name equal to the name input. */
403 wchar_t internal_port_query
[2048] = L
"SELECT * from "
404 L
"Msvm_EthernetPortAllocationSettingData WHERE ElementName = \"" ;
406 wide_name
= malloc((strlen(name
) + 1) * sizeof(wchar_t));
407 if (wide_name
== NULL
) {
408 VLOG_WARN("Could not allocate memory for wide string");
413 if (!tranform_wide(name
, wide_name
)) {
417 wcscat_s(internal_port_query
, sizeof(internal_port_query
), wide_name
);
419 wcscat_s(internal_port_query
, sizeof(internal_port_query
), L
"\"");
421 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
424 WBEM_FLAG_FORWARD_ONLY
|
425 WBEM_FLAG_RETURN_IMMEDIATELY
,
434 /* Get the element path on the switch which will be deleted. */
435 if (!get_first_element(penumerate
, &pcls_obj
)) {
439 penumerate
->lpVtbl
->Release(penumerate
);
442 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
448 pcls_obj
->lpVtbl
->Release(pcls_obj
);
451 /* Get the class object and the parameters it can have. */
452 hres
= psvc
->lpVtbl
->GetObject(psvc
,
453 L
"Msvm_VirtualEthernetSwitchManagementService", 0, NULL
, &pcls_obj
,
461 hres
= pcls_obj
->lpVtbl
->GetMethod(pcls_obj
, L
"RemoveResourceSettings", 0,
462 &pinput_params
, NULL
);
468 pcls_obj
->lpVtbl
->Release(pcls_obj
);
471 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
480 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
487 VariantClear(&vt_prop
);
488 VariantInit(&vt_prop
);
489 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
490 variant_array
.parray
= psa
;
492 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings", 0,
499 /* Get the object of the Msvm_VirtualEthernetSwitchManagementService which
500 * we need to invoke the port deletion. */
501 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
504 L
"Msvm_VirtualEthernetSwitchManagementService",
505 WBEM_FLAG_FORWARD_ONLY
|
506 WBEM_FLAG_RETURN_IMMEDIATELY
,
515 if (!get_first_element(penumerate
, &pcls_obj
)) {
519 penumerate
->lpVtbl
->Release(penumerate
);
522 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
529 pcls_obj
->lpVtbl
->Release(pcls_obj
);
532 /* Invoke the delete port method. */
533 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
534 L
"RemoveResourceSettings", 0,
535 pcontext
, pclass_instance
, &pout_params
,
541 VariantClear(&vt_prop
);
542 VariantInit(&vt_prop
);
544 hres
= pout_params
->lpVtbl
->Get(pout_params
, L
"ReturnValue", 0,
552 unsigned int retvalue
= 0;
553 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
559 if (retvalue
!= 0 && retvalue
!= job_wait
) {
564 if (retvalue
== job_wait
) {
565 WCHAR job_path
[2048];
566 hres
= get_str_value(pout_params
, L
"Job", job_path
,
567 sizeof(job_path
) / sizeof(WCHAR
));
572 hres
= wait_for_job(psvc
, job_path
);
579 VariantClear(&vt_prop
);
581 if (pcontext
!= NULL
) {
582 pcontext
->lpVtbl
->Release(pcontext
);
586 SafeArrayDestroy(psa
);
589 if (pcls_obj
!= NULL
) {
590 pcls_obj
->lpVtbl
->Release(pcls_obj
);
593 if (wide_name
!= NULL
) {
598 get_hres_error(hres
);
600 if (pinput_params
!= NULL
) {
601 pinput_params
->lpVtbl
->Release(pinput_params
);
602 pinput_params
= NULL
;
604 if (pout_params
!= NULL
) {
605 pout_params
->lpVtbl
->Release(pout_params
);
609 psvc
->lpVtbl
->Release(psvc
);
613 ploc
->lpVtbl
->Release(ploc
);
616 if (pclass_instance
!= NULL
) {
617 pclass_instance
->lpVtbl
->Release(pclass_instance
);
618 pclass_instance
= NULL
;
620 if (penumerate
!= NULL
) {
621 penumerate
->lpVtbl
->Release(penumerate
);
629 /* This function will create an internal port on the switch given a given name
630 * executing the method AddResourceSettings as per documentation:
631 * https://msdn.microsoft.com/en-us/library/hh850019%28v=vs.85%29.aspx.
632 * It will verify if the port is already defined, in which case it will use
633 * the specific port, and if the forwarding extension "Open vSwitch Extension"
634 * is enabled and running only on a single switch.
635 * After the port is created and bound to the switch we will disable the
636 * created net adapter and rename it to match the OVS bridge name .*/
638 create_wmi_port(char *name
) {
640 boolean retval
= true;
642 BSTR text_object_string
= NULL
;
644 IWbemLocator
*ploc
= NULL
;
645 IWbemContext
*pcontext
= NULL
;
646 IWbemServices
*psvc
= NULL
;
647 IEnumWbemClassObject
*penumerate
= NULL
;
648 IWbemClassObject
*default_settings_data
= NULL
;
649 IWbemClassObject
*default_system
= NULL
;
650 IWbemClassObject
*pcls_obj
= NULL
;
651 IWbemClassObject
*pclass
= NULL
;
652 IWbemClassObject
*pinput_params
= NULL
;
653 IWbemClassObject
*pclass_instance
= NULL
;
654 IWbemObjectTextSrc
*text_object
= NULL
;
655 IWbemClassObject
*pout_params
= NULL
;
657 wchar_t *wide_name
= NULL
;
659 VARIANT switch_setting_path
;
661 SAFEARRAY
*psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
662 VARIANT variant_array
;
665 VariantInit(&vt_prop
);
666 VariantInit(&switch_setting_path
);
667 sanitize_port_name(name
);
670 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
675 if (!initialize_wmi(&ploc
, &pcontext
)) {
676 VLOG_WARN("Could not initialize DCOM");
681 if (!connect_set_security(ploc
, pcontext
, L
"Root\\Virtualization\\v2",
683 VLOG_WARN("Could not connect and set security for virtualization");
688 /* Check if the element already exists on the switch. */
689 wchar_t internal_port_query
[2048] = L
"SELECT * FROM "
690 L
"Msvm_InternalEthernetPort WHERE ElementName = \"";
692 wide_name
= malloc((strlen(name
) + 1) * sizeof(wchar_t));
693 if (wide_name
== NULL
) {
694 VLOG_WARN("Could not allocate memory for wide string");
699 if (!tranform_wide(name
, wide_name
)) {
703 wcscat_s(internal_port_query
, sizeof(internal_port_query
), wide_name
);
705 wcscat_s(internal_port_query
, sizeof(internal_port_query
), L
"\"");
706 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
709 WBEM_FLAG_FORWARD_ONLY
|
710 WBEM_FLAG_RETURN_IMMEDIATELY
,
719 if (get_first_element(penumerate
, &pcls_obj
)) {
720 VLOG_WARN("Port with name: %s already defined on the switch", name
);
723 penumerate
->lpVtbl
->Release(penumerate
);
726 /* Check if the extension is enabled and running. Also check if the
727 * the extension is enabled on more than one switch. */
728 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
731 L
"FROM Msvm_EthernetSwitchExtension "
733 L
"ElementName=\"Open vSwitch Extension\" "
734 L
"AND EnabledState=2 "
735 L
"AND HealthState=5",
736 WBEM_FLAG_FORWARD_ONLY
|
737 WBEM_FLAG_RETURN_IMMEDIATELY
,
746 if (!get_first_element(penumerate
, &pcls_obj
)) {
747 VLOG_WARN("Open vSwitch Extension is not enabled on any switch");
751 wcscpy_s(internal_port_query
, sizeof(internal_port_query
),
752 L
"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name = \"");
754 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"SystemName", 0,
761 wcscat_s(internal_port_query
, sizeof(internal_port_query
),
764 VariantClear(&vt_prop
);
765 pcls_obj
->lpVtbl
->Release(pcls_obj
);
768 if (get_first_element(penumerate
, &pcls_obj
)) {
769 VLOG_WARN("The extension is activated on more than one switch, "
770 "aborting operation. Please activate the extension on a "
775 penumerate
->lpVtbl
->Release(penumerate
);
777 if (pcls_obj
!= NULL
) {
778 pcls_obj
->lpVtbl
->Release(pcls_obj
);
782 /* Get the switch object on which the extension is activated. */
783 wcscat_s(internal_port_query
, sizeof(internal_port_query
), L
"\"");
784 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
787 WBEM_FLAG_FORWARD_ONLY
|
788 WBEM_FLAG_RETURN_IMMEDIATELY
,
797 if (!get_first_element(penumerate
, &pcls_obj
)) {
798 VLOG_WARN("Could not get the switch object on which the extension is"
803 penumerate
->lpVtbl
->Release(penumerate
);
806 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"ElementName", 0, &vt_prop
, 0, 0);
813 wcscpy_s(internal_port_query
, sizeof(internal_port_query
),
814 L
"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData WHERE "
815 L
"ElementName = \"");
817 wcscat_s(internal_port_query
, sizeof(internal_port_query
),
819 VariantClear(&vt_prop
);
821 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"Name", 0, &vt_prop
, 0, 0);
827 pcls_obj
->lpVtbl
->Release(pcls_obj
);
830 /* Should be enough to give the InstanceID, from msdn documentation:
831 * Uniquely identifies an instance of this class. This property is
832 * inherited from CIM_SettingData and is always
833 * set to "Microsoft:GUID\DeviceSpecificData". */
834 wcscat_s(internal_port_query
, sizeof(internal_port_query
),
835 L
"\" AND InstanceID = \"Microsoft:");
836 wcscat_s(internal_port_query
, sizeof(internal_port_query
),
838 wcscat_s(internal_port_query
, sizeof(internal_port_query
),
841 VariantClear(&vt_prop
);
843 /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to the switch
844 * object on which the extension is activated. */
845 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
848 WBEM_FLAG_FORWARD_ONLY
|
849 WBEM_FLAG_RETURN_IMMEDIATELY
,
858 if (!get_first_element(penumerate
, &pcls_obj
)) {
859 VLOG_WARN("Could not get the first "
860 "Msvm_VirtualEthernetSwitchSettingData object");
864 penumerate
->lpVtbl
->Release(penumerate
);
867 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &switch_setting_path
,
874 pcls_obj
->lpVtbl
->Release(pcls_obj
);
877 /* Retrieve a default allocation port. This object will be later filled
878 * with optional data to create an switch internal port. */
879 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
882 L
"Msvm_EthernetPortAllocationSettingData "
883 L
"WHERE InstanceID LIKE '%%%%\\\\Default' "
884 L
"AND ResourceSubType = "
885 L
"'Microsoft:Hyper-V:Ethernet Connection'",
886 WBEM_FLAG_FORWARD_ONLY
|
887 WBEM_FLAG_RETURN_IMMEDIATELY
,
896 if (!get_first_element(penumerate
, &default_settings_data
)) {
897 VLOG_WARN("Could not retrieve default allocation port object");
901 penumerate
->lpVtbl
->Release(penumerate
);
904 /* Retrieve the default computer system on which the port allocation will
906 * Instead of querying using Description, we can query using InstallDate.
907 * From MSDN documentation regarding InstallDate:
908 * The date and time the virtual machine configuration was created for
909 * a virtual machine, or Null, for a management operating system. */
910 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
912 L
"SELECT * FROM Msvm_ComputerSystem WHERE "
913 L
"InstallDate is NULL",
914 WBEM_FLAG_FORWARD_ONLY
|
915 WBEM_FLAG_RETURN_IMMEDIATELY
,
924 if (!get_first_element(penumerate
, &default_system
)) {
925 VLOG_WARN("Could not retrieve default computer system object");
930 hres
= default_system
->lpVtbl
->Get(default_system
, L
"__PATH",
936 penumerate
->lpVtbl
->Release(penumerate
);
940 hres
= SafeArrayPutElement(psa
, count
, vt_prop
.bstrVal
);
947 VariantClear(&vt_prop
);
948 variant_array
.vt
= VT_ARRAY
| VT_BSTR
;
949 variant_array
.parray
= psa
;
950 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
958 hres
= psvc
->lpVtbl
->GetObject(psvc
,
959 L
"Msvm_VirtualEthernetSwitchManagementService",
960 0, NULL
, &pclass
, NULL
);
966 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"AddResourceSettings", 0,
967 &pinput_params
, NULL
);
973 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
980 /* Store the switch setting path retrieved above in the affected
981 * configuration field of the class instance. */
982 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
,
983 L
"AffectedConfiguration", 0,
984 &switch_setting_path
, 0);
991 /* Store the port name in the ElementName field of the default allocation
993 vt_prop
.vt
= VT_BSTR
;
994 vt_prop
.bstrVal
= SysAllocString(wide_name
);
995 hres
= default_settings_data
->lpVtbl
->Put(default_settings_data
,
998 VariantClear(&vt_prop
);
1004 /* Retrieve and store the serialized data of the modified default switch
1006 hres
= CoCreateInstance(&CLSID_WbemObjectTextSrc
,
1008 CLSCTX_INPROC_SERVER
,
1009 &IID_IWbemObjectTextSrc
,
1010 (void**)&text_object
);
1016 hres
= text_object
->lpVtbl
->GetText(text_object
, 0,
1017 default_settings_data
,
1018 WMI_OBJ_TEXT_WMI_DTD_2_0
,
1020 &text_object_string
);
1025 hres
= SafeArrayDestroy(psa
);
1027 VLOG_WARN("Could not clear the data of the array");
1032 psa
= SafeArrayCreateVector(VT_BSTR
, 0, 1);
1035 VLOG_WARN("Could not allocate memory for a SAFEARRAY");
1041 variant_array
.parray
= psa
;
1042 hres
= SafeArrayPutElement(psa
, count
, text_object_string
);
1047 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"ResourceSettings",
1048 0, &variant_array
, 0);
1054 /* Get the object of the switch service. */
1055 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1058 L
"Msvm_VirtualEthernetSwitchManagementService",
1059 WBEM_FLAG_FORWARD_ONLY
|
1060 WBEM_FLAG_RETURN_IMMEDIATELY
,
1068 if (!get_first_element(penumerate
, &pcls_obj
)) {
1069 VLOG_WARN("Could not get the object of the switch service");
1073 penumerate
->lpVtbl
->Release(penumerate
);
1076 hres
= pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1081 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1084 /* Try to add the port to the switch. */
1085 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
,
1086 L
"AddResourceSettings", 0,
1087 pcontext
, pclass_instance
, &pout_params
,
1094 unsigned int retvalue
= 0;
1095 hres
= get_uint_value(pout_params
, L
"ReturnValue", &retvalue
);
1101 if (retvalue
!= 0 && retvalue
!= job_wait
) {
1106 if (retvalue
== job_wait
) {
1107 WCHAR job_path
[2048];
1108 hres
= get_str_value(pout_params
, L
"Job", job_path
,
1109 sizeof(job_path
) / sizeof(WCHAR
));
1114 hres
= wait_for_job(psvc
, job_path
);
1121 pclass
->lpVtbl
->Release(pclass
);
1123 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1124 pclass_instance
= NULL
;
1125 pinput_params
->lpVtbl
->Release(pinput_params
);
1126 pinput_params
= NULL
;
1127 psvc
->lpVtbl
->Release(psvc
);
1129 VariantClear(&vt_prop
);
1131 if (!connect_set_security(ploc
, pcontext
, L
"Root\\StandardCimv2",
1133 VLOG_WARN("Could not connect and set security for CIM");
1138 wcscpy_s(internal_port_query
, sizeof(internal_port_query
),
1139 L
"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
1140 wcscat_s(internal_port_query
, sizeof(internal_port_query
), wide_name
);
1141 wcscat_s(internal_port_query
, sizeof(internal_port_query
), L
"%%'");
1143 /* Get the object with the port name equal to name on the CIM. */
1144 hres
= psvc
->lpVtbl
->ExecQuery(psvc
,
1146 internal_port_query
,
1147 WBEM_FLAG_FORWARD_ONLY
|
1148 WBEM_FLAG_RETURN_IMMEDIATELY
,
1152 if (!get_first_element(penumerate
, &pcls_obj
)) {
1153 VLOG_WARN("Element name: %s not found in CIM", name
);
1157 penumerate
->lpVtbl
->Release(penumerate
);
1159 pcls_obj
->lpVtbl
->Get(pcls_obj
, L
"__PATH", 0, &vt_prop
, 0, 0);
1160 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1163 /* Disable the adapter with port name equal with name. */
1164 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Disable", 0,
1165 pcontext
, NULL
, NULL
, NULL
);
1172 hres
= psvc
->lpVtbl
->GetObject(psvc
, L
"MSFT_NetAdapter", 0, NULL
, &pclass
,
1179 hres
= pclass
->lpVtbl
->GetMethod(pclass
, L
"Rename", 0, &pinput_params
,
1186 hres
= pinput_params
->lpVtbl
->SpawnInstance(pinput_params
, 0,
1193 VariantInit(&new_name
);
1194 new_name
.vt
= VT_BSTR
;
1195 new_name
.bstrVal
= wide_name
;
1196 hres
= pclass_instance
->lpVtbl
->Put(pclass_instance
, L
"NewName", 0,
1202 hres
= psvc
->lpVtbl
->ExecMethod(psvc
, vt_prop
.bstrVal
, L
"Rename", 0,
1203 pcontext
, pclass_instance
, NULL
, NULL
);
1209 if (text_object_string
!= NULL
) {
1210 SysFreeString(text_object_string
);
1211 text_object_string
= NULL
;
1214 SafeArrayDestroy(psa
);
1218 ploc
->lpVtbl
->Release(ploc
);
1221 if (pcontext
!= NULL
) {
1222 pcontext
->lpVtbl
->Release(pcontext
);
1226 psvc
->lpVtbl
->Release(psvc
);
1229 if (penumerate
!= NULL
) {
1230 penumerate
->lpVtbl
->Release(penumerate
);
1233 if (default_settings_data
!= NULL
) {
1234 default_settings_data
->lpVtbl
->Release(default_settings_data
);
1235 default_settings_data
= NULL
;
1237 if (default_system
!= NULL
) {
1238 default_system
->lpVtbl
->Release(default_system
);
1239 default_system
= NULL
;
1241 if (pcls_obj
!= NULL
) {
1242 pcls_obj
->lpVtbl
->Release(pcls_obj
);
1245 if (pclass
!= NULL
) {
1246 pclass
->lpVtbl
->Release(pclass
);
1249 if (pinput_params
!= NULL
) {
1250 pinput_params
->lpVtbl
->Release(pinput_params
);
1251 pinput_params
= NULL
;
1253 if (pclass_instance
!= NULL
) {
1254 pclass_instance
->lpVtbl
->Release(pclass_instance
);
1255 pclass_instance
= NULL
;
1257 if (text_object
!= NULL
) {
1258 text_object
->lpVtbl
->Release(text_object
);
1261 if (pout_params
!= NULL
) {
1262 pout_params
->lpVtbl
->Release(pout_params
);
1265 if (wide_name
!= NULL
) {
1269 VariantClear(&vt_prop
);
1270 VariantClear(&switch_setting_path
);
1273 get_hres_error(hres
);