WMI calling method - c++

I'm trying to change Intel network adapter settings using WMI. Accessing the classes works fine but according to the Intel documentation page 40 i need to call two methods in order to apply those changes.
So the IANet_NetService class should have the methods BeginApply and Apply. When I check this using PowerShell command get-wmiobject -namespace root\intelncs2 -class IAnet_NetService | get-member I can confirm that these methods are present.
The Intel documentation says I should enumerate the single instance in IANet_NetService.
So when I use CreateInstanceEnum method it will give me one result in the enumeration, but when I try to enumerate the methods for this instance, it won't find any.
Later I tried to use CreateClassEnum which had no results.
At last I tried a simple GetObject call to get the IANet_NetService item. With this item I was also able to enumerate the methods and find the BeginApply and Apply methods.
It is also possible to call GetMethod to receive the signature information. For the BeginApply method it has no input parameters which is correct according to the Intel docs. So I try to execute this method using pService->ExecMethod(L"IAnet_NetService", L"BeginApply", 0, 0, 0, &pOutInst, 0); which return WBEM_E_INVALID_METHOD_PARAMETERS. MSDN says this may be returned when the input parameters are wrong or I'm missing a [static] qualifier on the method.
The input parameters are correct, but I do not know what the missing [static] qualifier means in this case.
Anyone knows how to call this method?

The problem was, that i needed to use the GetObject/GetMethod combination to retrieve the input parameters and after this get the only instance of the object and ask for it's path. This path replaced L"IAnet_NetService" on the ExecMethod call and it's working.

WMI Method call without parameters:
This one is the exact code reference:
IEnumWbemClassObject * enum_obj;
hres = pSvc>CreateInstanceEnum(_bstr_t(L"IANet_NetService"),WBEM_FLAG_RETURN_IMMEDIATELY , NULL ,&enum_obj);
IWbemClassObject * spInstance;
ULONG uNumOfInstances = 0;
hres = enum_obj->Next(10000, 1,&spInstance,&uNumOfInstances);
VARIANT path;
hres = spInstance->Get(_bstr_t("__Path"), 0,&path, 0, 0);
IWbemClassObject *results = NULL;
hres = pSvc->ExecMethod( path.bstrVal, _bstr_t( L"Apply" ), 0,
NULL,NULL,&results, NULL );

Related

How can I create a JavaScript object in Internet Explorer from C++

I'm using an external C++ application to control Internet Explorer (version is 11, but that seems unimportant for this example). Part of this control is being able to run arbitrary JavaScript in the browser's context. To enable that control, I'd like to be able to create a JavaScript object (or array, or function, etc.), represented by an appropriate IDispatch variant, that I can use in subsequent script calls. There are some examples online, including some from Microsoft, that would indicate such a thing should be possible, by finding and invoking the Object constructor.
Below is some sample code, cribbed from the aforementioned examples, that should do the trick. However, when I execute the code, I get an E_INVALIDARG ("One or more arguments are invalid") HRESULT returned. What am I doing wrong, and how do I fix the issue?
// Example assumes that you're using an ATL project which give access to
// the "CCom" wrapper classes, and that you have the ability to retrieve
// an IHTMLDocument2 object pointer.
int CreateJavaScriptObject(IHTMLDocument2* script_engine_host, CComVariant* created_object) {
// NOTE: Proper return code checking and error handling
// has been omitted for brevity
int status_code = 0;
CComPtr<IDispatch> script_dispatch;
HRESULT hr = script_engine_host->get_Script(&script_dispatch);
CComPtr<IDispatchEx> script_engine;
hr = script_dispatch->QueryInterface<IDispatchEx>(&script_engine);
// Create the variables we need
DISPPARAMS no_arguments_dispatch_params = { NULL, NULL, 0, 0 };
CComVariant created_javascript_object;
DISPID dispatch_id;
// Find the javascript object using the IDispatchEx of the script engine
std::wstring item_type = L"Object";
CComBSTR name(item_type.c_str());
hr = script_engine->GetDispID(name, 0, &dispatch_id);
// Create the jscript object by calling its constructor
// The below InvokeEx call returns E_INVALIDARG in this case
hr = script_engine->InvokeEx(dispatch_id,
LOCALE_USER_DEFAULT,
DISPATCH_CONSTRUCT,
&no_arguments_dispatch_params,
&created_javascript_object,
NULL,
NULL);
*created_object = created_javascript_object;
return status_code;
}
Potential answerers desiring a fully compilable solution can find a version of the above code in a GitHub repo. The repo includes a Visual Studio 2017 solution that creates a console application which will reproduce the issue, including launching Internet Explorer and obtaining a reference to the required IHTMLDocument2 object. Note that the version in the repo has somewhat more complete error handling than the above sample, in which it was omitted for brevity.

How to call Win32_NetworkAdapterConfiguration::EnableDHCP() for a specific adapter in C++?

One of my tasks it to configure network adapters for DHCP/static IP, and the only way I found to do this is using Win32_NetworkAdapterConfiguration class.
WMI is new to me, and it seems to use it in C++ (Qt/MinGW) is not that easy, and most things I found in the WWW deal with .NET, PowerShell or VBScript. However, I already succeeded in querying information, for example the MAC address for a specific adapter.
I already read the MSDN: Calling a Provider method on MSDN, but in looking forware to WIn32_NetworkAdapterConfiguration there is one thing I don't unstand.
My IEnumWbemClassObject is the result of a SELECT * FROM Win32_NetworkAdapterConfiguration WHERE InterfaceIndex=n (n is a number, of course), and returns IWbemClassObject for the specific adapter.
How to I tell ExecMethod which instance of Win32_NetworkAdapterConiguration to use when calling the EnableDHCP()/EnableStatic() methods (in meaning of the IWbemClassObject I will recieve when i enumerate the result of my query)?
While looking for a example for passing string arrays to ExecMethod() if found this thread at CodeProject which execatly fit to my tasks. As stated in the comments above, the path of the object instance (not the class path!) must be passed to the "strObjectPath" parameter of ExecMethod.

ADO Command saying that I am inserting NULL, when I'm not

I'm using ADO to communicate with my Sybase server..
This is how I'm executing a simple command:
_ConnectionPtr m_ConnPtr;
//... Instantiate connection
_CommandPtr m_CommPtr;
m_CommPtr->CreateInstance(__uuidof(Command))
m_CommPtr->ActiveConnection = m_ConnPtr;
Variant m_variant;
m_variant.SetString("My Param Value");
_ParameterPtr ParamPtr;
ParamPtr = m_CommPtr->CreateParameter("#StrParam", (DataTypeEnum) m_variant.vt, adParamInput, NULL, m_variant);
m_CommPtr->Parameters->Append(PrmPtr);
m_CommPtr->CommandText = "EXECUTE my_stored_procedure #StrParam";
m_CommPtr->Execute(NULL, NULL, adOptionUnspecified);
#StrParam is supposed to be a VarChar type..
Running this gives me an error:
Attempt to insert NULL value into column 'StrParam'. table 'MYTABLE';
column does not allow nulls. Update fails.
I'm not sure why I'm getting this error, since I am specifiying its value ("My Param Value")..
Does anyone know what I'm doing wrong?
(I didn't include the Stored procedure,, because I'm sure there's nothing wrong with the procedure itself.. Other application using the same procedure works fine. So there must be something wrong with how I'm using the parametized command)
I have no clue what your Variant class even is. But the traditional variant type (vt) and the ADO data type are not synonymous. Second, you're not setting up the call nor parameters correctly for a typical stored-proc invoke.
Below is how you would do this using a standard stored proc call and variant_t from the comutil library:
_CommandPtr m_CommPtr(__uuidof(Command));
m_CommPtr->ActiveConnection = m_ConnPtr;
m_CommPtr->CommandType = adoCmdStoredProc;
m_CommPtr->CommandText = L"my_stored_procedure";
// setup parameter
variant_t vParam = L"My Param Value";
_ParameterPtr ParamPtr = m_CommPtr->CreateParameter(L"#StrParam", adBSTR, adParamInput, 0, vParam);
m_CommPtr->Parameters->Append(ParamPtr);
m_CommPtr->Execute(NULL, NULL, adOptionUnspecified);
Note that the ParamPtr is generally optional and you can straight-away append the parameter to the command's Parameters collection if you don't need it for anything else, like this:
m_CommPtr->Parameters->Append(m_CommPtr->CreateParameter(
L"#StrParam", adBSTR, adParamInput, 0, vParam));
The method you're using is common for parameters that are both input and output, as you retain the parameter object reference to extract the output side of the parameter. I see no evidence of that in your call, which is the only reason I mention it here.
Also note that unless the command returns rows for a result set you should also invoke with adExecuteNoRecords for the execution third option (which is typical for many fire-and-forget stored procedure executions)
Finally, the names of the parameters are not important unless you use the NamedParameters property of the command object. This is commonly done when you have additional parameters with default values that you would like to retain, setting only specific parameters as part of your append list.
Best of luck.

Unable to set user_version in SQLite

I am trying to use the user_version feature of an SQLite database. I am unable to actually set the user_version and I am not sure why. I have tried various ways of executing a query to update the user_version, and have searched extensively online and am now at a total loss.
Here is my query string.
const std::string kSetUserVersion = "PRAGMA user_version = 1;";
And here is where I am trying to set the user_version, however my result is still 0.
// Set the user version and check it is correct.
sqlite3_exec(dbConnection->db_handle, kSetUserVersion.c_str(), nullptr, nullptr, &db_err); // <-- this is not working!
long currentVersion = sqlite3_exec(dbConnection->db_handle, kGetUserVersion.c_str(), nullptr, nullptr, &db_err);
// If the PRAGMA statement fails, no error returns and it fails silently, so having to add check to see if it has worked.
if (currentVersion != 1) // Setting the user_version has failed.
{
throw DatabaseAccessException(sqlite3_errmsg(dbConnection->db_handle));
}
Any help is much appreciated.
sqlite3_exec() return value is a status/error code and not the value from your query.
To get the query result value, there are two primary options:
Use sqlite3_prepare_v2(), sqlite_step() for SQLITE_ROW and access the data with e.g. sqlite3_column_int(), finalizing the prepared query with sqlite3_finalize().
Supply a callback function as the third argument to your sqlite3_exec() to capture the value. See e.g. here for example: Proper use of callback function of sqlite3 in C++

Why is DNSServiceProcessResult calling my callback twice?

I've built the Qt+Bonjour integration demo from Qt Quarterly, but one thing I can't wrap my head around is that a single call to DNSServiceProcessResult() is calling the DNSServiceResolveReply callback function twice.
It should be calling it once! What I mean is, this single line:
DNSServiceErrorType err = DNSServiceProcessResult(dnssref);
Results in the DNSServiceResolveReply callback I passed to DNSServiceResolve to be called twice.
The interfaceIndex is different - first time it is 10000010, second time it is 20, but I have no idea what that means.
All other parameters are the same between calls (except flags, of course, which is kDNSServiceFlagsMoreComing the first time and 0 the second).
Edit
This is how I call the DNSServiceResolve function.
DNSServiceErrorType err = DNSServiceResolve(&dnssref, 0, 0,
record.serviceName.toUtf8().constData(),
record.registeredType.toUtf8().constData(),
record.replyDomain.toUtf8().constData(),
(DNSServiceResolveReply)bonjourResolveReply, this);
I found the problem, it was that I was passing 0 for the interfaceIndex when calling DNSServiceResolve.
The docs say that:
If this resolve call is
as a result of a currently active DNSServiceBrowse() operation, then the
interfaceIndex should be the index reported in the DNSServiceBrowseReply
callback. If this resolve call is using information previously saved
(e.g. in a preference file) for later use, then use interfaceIndex 0, because
the desired service may now be reachable via a different physical interface.