Related
I have a block of of code
if(!CreateProcessWithLogonW(
szUserName,
NULL,
szPassword,
LOGON_WITH_PROFILE,
L"C:\\Windows\\System32\\cmd.exe", // file to execute
NULL,
NORMAL_PRIORITY_CLASS | CREATE_BREAKAWAY_FROM_JOB, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
)){
ReportError(L"Create Process");
}
ReportError is not invoked, but csrss.exe pops up with
What am I doing wrong?!
The username and password ARE correct.
the whole file:
// cmd.cpp : Defines the entry point for the console application.
//
#include <Windows.h>
#include <Lmcons.h>
#include <iostream>
#include <ctype.h>
#include <string>
#include <stdio.h>
#define winstring LPWSTR
#define stcas(x) static_cast<x>
#define INFO_BUFFER_SIZE 260
using namespace std;
void ReportError(LPCWSTR pszFunction, DWORD dwError = GetLastError())
{
wprintf(L"%s failed w/err 0x%08lx\n", pszFunction, dwError);
}
int main()
{
TCHAR un[UNLEN+1];
DWORD size = UNLEN + 1;
GetUserName(un, &size);
string una(un);
bool sys = !una.compare("SYSTEM");
/*
if(!sys) {
system("cls");
system("title Command Prompt");
system("cmd");
return 0;
}
*/
wchar_t szUserName[INFO_BUFFER_SIZE] = {};
wchar_t szPassword[INFO_BUFFER_SIZE] = {};
wchar_t *pc = NULL;
HANDLE hToken = NULL;
BOOL fSucceeded = FALSE;
BOOL logon = FALSE;
printf("Enter the username: ");
fgetws(szUserName, ARRAYSIZE(szUserName), stdin);
pc = wcschr(szUserName, '\n');
if (pc != NULL) *pc = '\0'; // Remove the trailing L'\n'
cout << endl;
//string un(szUserName);
printf("Enter the password: ");
fgetws(szPassword, ARRAYSIZE(szPassword), stdin);
pc = wcschr(szPassword, '\n');
if (pc != NULL) *pc = '\0'; // Remove the trailing L'\n'
if (!LogonUserW(szUserName, NULL, szPassword, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken))
{
ReportError(L"Logon");
goto Cleanup;
}
else logon = true;
HANDLE phToken = NULL;
BOOL dup = FALSE;
if(!DuplicateTokenEx(hToken, TOKEN_DUPLICATE|TOKEN_IMPERSONATE|TOKEN_QUERY, NULL, SecurityImpersonation, TokenPrimary, &phToken)){
ReportError(L"DUPLICATE TOKEN");
}
else dup = TRUE;
// Impersonate the logged on user.
if (!ImpersonateLoggedOnUser(phToken))
{
ReportError(L"imp");
goto Cleanup;
}
fSucceeded = true;
Cleanup:
// Clean up the buffer containing sensitive password.
LPTSTR szCmdline[] = {"cmd"};
STARTUPINFOW si;
PROCESS_INFORMATION pi;
TCHAR uni[UNLEN+1];
DWORD sizei = UNLEN + 1;
GetUserName(uni, &sizei);
string unai(uni);
cout << unai << endl;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
system("pause");
// If the impersonation was successful, undo the impersonation.
if (fSucceeded && logon)
{
system("cls");
system("title Command Prompt");
//system("cmd");
if(!CreateProcessWithLogonW(
szUserName,
NULL,
szPassword,
LOGON_WITH_PROFILE,
L"cmd.exe", // file to exec
NULL,
NORMAL_PRIORITY_CLASS | CREATE_BREAKAWAY_FROM_JOB, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
)){
ReportError(L"Create Process");
}
if (!RevertToSelf())
{
ReportError(L"Undo Imp");
}
}
SecureZeroMemory(szPassword, sizeof(szPassword));
system("pause");
}
The code you posted works for me if I skip the calls to LogonUser, DuplicateToken and ImpersonateLoggedOnUser. You don't want to impersonate another user in order to call CreateProcessWithLogon since it basically does that for you, so just remove all that logic to do the impersonation.
Impersonating a user could also cause your program to be unable to launch an application at all if the target application requires a higher level of privilege than the user has.
i'm writting a C++ WMI utility class which wraps the WMI stuff to help my further WMI query. i encountered a problem when accessing a Win32_SecurityDescriptor instance.
i used the WQL query "Select * from Win32_LogicalShareSecuritySetting" to get all the Win32_LogicalShareSecuritySetting instances. then called the GetSecurityDescriptor method of Win32_LogicalShareSecuritySetting instance to get a Win32_SecurityDescriptor instance. But when i attempted to retrieve some property like "__PATH" from the Win32_SecurityDescriptor instance, i got a 0xC0000005 Access Violation messagebox.
i wrote my code in C++, but i think the problem should be common.
I also used the wbemtest tool by Microsoft for test but didn't find a way to display a Win32_SecurityDescriptor instance. Why is Win32_SecurityDescriptor so special?
here's all my code, you can try it in your VC, mine is 6. Windows SDK maybe needed.
Access Violation found in the caller code:
CString strSDInstancePath = wmiSearcher->getStringFromObject(pSDInstance, "__PATH");
ADWMISearch.cpp
#include "StdAfx.h"
#include "ADWMISearch.h"
#include <comdef.h>
# pragma comment(lib, "wbemuuid.lib")
# pragma comment(lib, "credui.lib")
# pragma comment(lib, "comsupp.lib")
#include <wincred.h>
#include <strsafe.h>
#include <iostream>
using namespace std;
DWORD ADWMISearch::WIN32_FROM_HRESULT_alternate(HRESULT hr)
{
DWORD dwResult;
if (hr < 0)
{
dwResult = (DWORD) hr;
return dwResult;
}
else
{
MyMessageBox_Error(_T("WIN32_FROM_HRESULT_alternate Error."), _T("Error"));
return -1;
}
}
IWbemServices* ADWMISearch::connect(CString strServerName, CString strServerIP, CString strDomainName, CString strUsername,
CString strPassword)
{
CString strComputerName = strServerName;
CString strFullUsername; //_T("adtest\\Administrator")
if (strDomainName == _T(""))
{
strUsername = _T("");
strFullUsername = _T("");
strPassword = _T("");
}
else
{
strFullUsername = strDomainName + _T("\\") + strUsername;
}
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
//cout << "Failed to initialize COM library. Error code = 0x"
// << hex << hres << endl;
MyMessageBox_Error(_T("connect"));
return NULL; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IDENTIFY, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
//char aaa[100];
//sprintf(aaa, "%x", hres);
if (FAILED(hres) && hres != RPC_E_TOO_LATE)
{
//cout << "Failed to initialize security. Error code = 0x"
// << hex << hres << endl;
CoUninitialize();
MyMessageBox_Error(_T("connect"));
return NULL; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
CoUninitialize();
MyMessageBox_Error(_T("connect"));
return NULL; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
bool useToken = TRUE;
bool useNTLM = FALSE;
// Get the user name and password for the remote computer
/*
CREDUI_INFO cui;
bool useToken = TRUE;
bool useNTLM = FALSE;
TCHAR pszName[CREDUI_MAX_USERNAME_LENGTH+1] = {0};
TCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1] = {0};
TCHAR pszDomain[CREDUI_MAX_USERNAME_LENGTH+1];
TCHAR pszUserName[CREDUI_MAX_USERNAME_LENGTH+1];
TCHAR pszAuthority[CREDUI_MAX_USERNAME_LENGTH+1];
BOOL fSave;
DWORD dwErr;
memset(&cui,0,sizeof(CREDUI_INFO));
cui.cbSize = sizeof(CREDUI_INFO);
cui.hwndParent = NULL;
// Ensure that MessageText and CaptionText identify
// what credentials to use and which application requires them.
cui.pszMessageText = _T("Press cancel to use process token");
cui.pszCaptionText = _T("Enter Account Information");
cui.hbmBanner = NULL;
fSave = FALSE;
dwErr = CredUIPromptForCredentials(
&cui, // CREDUI_INFO structure
_T(""), // Target for credentials
NULL, // Reserved
0, // Reason
pszName, // User name
CREDUI_MAX_USERNAME_LENGTH+1, // Max number for user name
pszPwd, // Password
CREDUI_MAX_PASSWORD_LENGTH+1, // Max number for password
&fSave, // State of save check box
CREDUI_FLAGS_GENERIC_CREDENTIALS |// flags
CREDUI_FLAGS_ALWAYS_SHOW_UI |
CREDUI_FLAGS_DO_NOT_PERSIST);
if(dwErr == ERROR_CANCELLED)
{
useToken = true;
}
else if (dwErr)
{
cout << "Did not get credentials " << dwErr << endl;
pLoc->Release();
CoUninitialize();
return 1;
}
*/
// change the computerName strings below to the full computer name
// of the remote computer
CString strAuthority;
if(!useNTLM)
{
//StringCchPrintf(pszAuthority, CREDUI_MAX_USERNAME_LENGTH+1, _T("kERBEROS:%s"), strComputerName);
strAuthority = _T("kERBEROS:") + strComputerName;
}
// Connect to the remote root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
//---------------------------------------------------------
CString strNetworkResource = _T("\\\\") + strComputerName + _T("\\root\\cimv2");
if (strFullUsername == _T(""))
{
hres = pLoc->ConnectServer(
_bstr_t(strNetworkResource),
NULL, // User name
NULL, // User password
NULL, // Locale
WBEM_FLAG_CONNECT_USE_MAX_WAIT, // Security flags
_bstr_t(strAuthority), // Authority
NULL, // Context object
&pSvc // IWbemServices proxy
);
}
else
{
hres = pLoc->ConnectServer(
_bstr_t(strNetworkResource),
_bstr_t(strFullUsername), // User name
_bstr_t(strPassword), // User password
NULL, // Locale
WBEM_FLAG_CONNECT_USE_MAX_WAIT, // Security flags
_bstr_t(strAuthority), // Authority
NULL, // Context object
&pSvc // IWbemServices proxy
);
}
if (FAILED(hres))
{
DWORD aaa = WIN32_FROM_HRESULT_alternate(hres);
//cout << "Could not connect. Error code = 0x"
// << hex << hres << endl;
pLoc->Release();
CoUninitialize();
MyMessageBox_Error(_T("connect"));
return NULL; // Program has failed.
}
//cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// step 5: --------------------------------------------------
// Create COAUTHIDENTITY that can be used for setting security on proxy
COAUTHIDENTITY *userAcct = NULL;
COAUTHIDENTITY authIdent;
if(!useToken)
{
memset(&authIdent, 0, sizeof(COAUTHIDENTITY));
authIdent.PasswordLength = strPassword.GetLength();
authIdent.Password = (USHORT*) _bstr_t(strPassword);
authIdent.Domain = (USHORT*) _bstr_t(strDomainName);
authIdent.DomainLength = strDomainName.GetLength();
authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
userAcct = &authIdent;
}
// Step 6: --------------------------------------------------
// Set security levels on a WMI connection ------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
userAcct, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
//cout << "Could not set proxy blanket. Error code = 0x"
// << hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
MyMessageBox_Error(_T("connect"));
return NULL; // Program has failed.
}
// Cleanup
// ========
pLoc->Release();
return pSvc;
}
vector<IWbemClassObject*> ADWMISearch::query(IWbemServices *pSvc, CString strDomainName, CString strPassword, CString strWQL)
{
vector<IWbemClassObject*> npResultObjects;
BOOL useToken = TRUE;
// step 5: --------------------------------------------------
// Create COAUTHIDENTITY that can be used for setting security on proxy
COAUTHIDENTITY *userAcct = NULL;
COAUTHIDENTITY authIdent;
if(!useToken)
{
memset(&authIdent, 0, sizeof(COAUTHIDENTITY));
authIdent.PasswordLength = strPassword.GetLength();
authIdent.Password = (USHORT*) _bstr_t(strPassword);
/*
LPTSTR slash = _tcschr(pszName, _T('\\'));
if( slash == NULL )
{
//cout << _T("Could not create Auth identity. No domain specified\n") ;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
StringCchCopy(pszUserName, CREDUI_MAX_USERNAME_LENGTH+1, slash+1);
authIdent.User = (USHORT*)pszUserName;
authIdent.UserLength = _tcslen(pszUserName);
StringCchCopyN(pszDomain, CREDUI_MAX_USERNAME_LENGTH+1, pszName, slash - pszName);
*/
authIdent.Domain = (USHORT*) _bstr_t(strDomainName);
authIdent.DomainLength = strDomainName.GetLength();
authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
userAcct = &authIdent;
}
// Step 7: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
HRESULT hResult;
hResult = pSvc->ExecQuery(
_bstr_t(_T("WQL")),
_bstr_t(strWQL), //_T("Select * from Win32_Share")
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hResult))
{
//cout << "Query for operating system name failed."
// << " Error code = 0x"
// << hex << hres << endl;
MyMessageBox_Error(_T("query"));
return npResultObjects; // Program has failed.
}
// Step 8: -------------------------------------------------
// Secure the enumerator proxy
hResult = CoSetProxyBlanket(
pEnumerator, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
userAcct, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hResult))
{
//cout << "Could not set proxy blanket on enumerator. Error code = 0x"
// << hex << hres << endl;
pEnumerator->Release();
MyMessageBox_Error(_T("query"));
return npResultObjects; // Program has failed.
}
// When you have finished using the credentials,
// erase them from memory.
// Step 9: -------------------------------------------------
// Get the data from the query in step 7 -------------------
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
npResultObjects.push_back(pclsObj);
/*
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
cout << _T("OS Name: ") << vtProp.bstrVal << endl;
// Get the value of the FreePhysicalMemory property
hr = pclsObj->Get(L"FreePhysicalMemory", 0, &vtProp, 0, 0);
cout << "Free physical memory(in kilobytes): " << vtProp.uintVal << endl;
VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
*/
}
// Cleanup
// ========
pEnumerator->Release();
return npResultObjects;
}
CString ADWMISearch::getStringFromObject(IWbemClassObject* pObject, CString strPropertyName)
{
_bstr_t bstrPropertyName = strPropertyName;
VARIANT vtProperty;
CString strProperty;
// Get the value of the property
VariantInit(&vtProperty);
HRESULT hResult = pObject->Get(bstrPropertyName, 0, &vtProperty, 0, 0);
if (SUCCEEDED(hResult) && V_VT(&vtProperty) == VT_BSTR)
{
strProperty = vtProperty.bstrVal;
VariantClear(&vtProperty);
return strProperty;
}
else
{
VariantClear(&vtProperty);
MyMessageBox_Error(_T("getStringsFromObjects"));
return _T("");
}
}
vector<CString> ADWMISearch::getStringsFromObjects(vector<IWbemClassObject*> npObjects, CString strPropertyName)
{
_bstr_t bstrPropertyName = strPropertyName;
vector<CString> nstrProperties;
for (int i = 0; i < npObjects.size(); i ++)
{
VARIANT vtProperty;
CString strProperty;
// Get the value of the property
VariantInit(&vtProperty);
HRESULT hResult = npObjects[i]->Get(bstrPropertyName, 0, &vtProperty, 0, 0);
if (SUCCEEDED(hResult) && V_VT(&vtProperty) == VT_BSTR)
{
CString strProperty = vtProperty.bstrVal;
nstrProperties.push_back(strProperty);
VariantClear(&vtProperty);
}
else
{
VariantClear(&vtProperty);
MyMessageBox_Error(_T("getStringsFromObjects"));
return nstrProperties;
}
}
return nstrProperties;
}
void ADWMISearch::clearObjects(vector<IWbemClassObject*> npObjects)
{
for (int i = 0; i < npObjects.size(); i ++)
{
npObjects[i]->Release();
npObjects[i] = NULL;
}
npObjects.clear();
}
IWbemClassObject* ADWMISearch::getWMIClass(IWbemServices *pSvc, CString strClassName)
{
HRESULT hResult;
IWbemClassObject* pClass = NULL;
hResult = pSvc->GetObject(_bstr_t(strClassName), 0, NULL, &pClass, NULL); //_T("Win32_Share")
if (!SUCCEEDED(hResult))
{
MyMessageBox_Error(_T("getWMIClass"));
return NULL;
}
else
{
return pClass;
}
}
IWbemClassObject* ADWMISearch::getObjectFromObject(IWbemClassObject *pObject, CString strArgumentName)
{
if (!pObject)
{
MyMessageBox_Error(_T("getObjectFromObject"));
return NULL;
}
HRESULT hResult;
VARIANT varArgument;
hResult = pObject->Get(_bstr_t(strArgumentName), 0, &varArgument, NULL, 0);
if (!SUCCEEDED(hResult))
{
VariantClear(&varArgument);
MyMessageBox_Error(_T("getObjectFromObject"));
return NULL;
}
//IWbemClassObject **ppResultObject;
IWbemClassObject *pResultObject2;
if (V_VT(&varArgument) == VT_UNKNOWN)
{
//ppResultObject = (IWbemClassObject **)varArgument.ppunkVal;
pResultObject2 = (IWbemClassObject *)varArgument.punkVal;
}
else if (V_VT(&varArgument) == VT_DISPATCH)
{
//ppResultObject = (IWbemClassObject **)varArgument.ppdispVal;
pResultObject2 = (IWbemClassObject *)varArgument.pdispVal;
}
else
{
VariantClear(&varArgument);
MyMessageBox_Error(_T("getObjectFromObject"));
return NULL;
}
VariantClear(&varArgument);
//IWbemClassObject *pResultObject = *ppResultObject;
//return pResultObject;
return pResultObject2;
}
IWbemClassObject* ADWMISearch::getObjectFromObjectWithCheck(IWbemClassObject *pOutParams, CString strArgumentName)
{
if (!pOutParams)
{
MyMessageBox_Error(_T("getObjectFromObjectWithCheck"));
return NULL;
}
HRESULT hResult;
VARIANT varReturnValue;
VARIANT varArgument;
hResult = pOutParams->Get(_bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0);
if (!SUCCEEDED(hResult))
{
VariantClear(&varReturnValue);
VariantClear(&varArgument);
MyMessageBox_Error(_T("getObjectFromObjectWithCheck"));
return NULL;
}
DWORD dwResult = varReturnValue.lVal;
hResult = pOutParams->Get(_bstr_t(strArgumentName), 0, &varArgument, NULL, 0);
if (!SUCCEEDED(hResult))
{
VariantClear(&varReturnValue);
VariantClear(&varArgument);
MyMessageBox_Error(_T("getObjectFromObjectWithCheck"));
return NULL;
}
//IWbemClassObject **ppResultObject;
IWbemClassObject *pResultObject2;
if (V_VT(&varArgument) == VT_UNKNOWN)
{
//ppResultObject = (IWbemClassObject **)varArgument.ppunkVal;
pResultObject2 = (IWbemClassObject *)varArgument.punkVal;
}
else if (V_VT(&varArgument) == VT_DISPATCH)
{
//ppResultObject = (IWbemClassObject **)varArgument.ppdispVal;
pResultObject2 = (IWbemClassObject *)varArgument.pdispVal;
}
else
{
VariantClear(&varReturnValue);
VariantClear(&varArgument);
MyMessageBox_Error(_T("getObjectFromObjectWithCheck"));
return NULL;
}
VariantClear(&varReturnValue);
VariantClear(&varArgument);
//IWbemClassObject *pResultObject = *ppResultObject;
//return pResultObject;
return pResultObject2;
}
vector<ADWMIParam> ADWMISearch::genObjectArguments(CString strArgName, IWbemClassObject *pObject)
{
vector<ADWMIParam> resultArgs;
resultArgs.push_back(ADWMIParam(strArgName, pObject));
return resultArgs;
}
IWbemClassObject* ADWMISearch::callStaticMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strMethodName)
{
return callStaticMethod(pSvc, pClass, strClassName, strMethodName, vector<ADWMIParam>());
}
IWbemClassObject* ADWMISearch::callStaticMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strMethodName, vector<ADWMIParam> &arguments)
{
_bstr_t bstrClassName = _bstr_t(strClassName);
_bstr_t bstrMethodName = _bstr_t(strMethodName);
BOOL bInParams;
BOOL bOutParams;
HRESULT hResult;
IWbemClassObject* pClass2 = getWMIClass(pSvc, strClassName);
IWbemClassObject* pInParamsDefinition = NULL;
IWbemClassObject* pOutParamsDefinition = NULL;
hResult = pClass2->GetMethod(bstrMethodName, 0, &pInParamsDefinition, &pOutParamsDefinition);
if (hResult != WBEM_S_NO_ERROR)
{
//pClass->Release();
MyMessageBox_Error(_T("callStaticMethod"));
return NULL;
}
if (pInParamsDefinition == NULL)
{
bInParams = FALSE;
}
else
{
bInParams = TRUE;
}
if (pOutParamsDefinition == NULL)
{
bOutParams = FALSE;
}
else
{
bOutParams = TRUE;
}
IWbemClassObject* pInParamsInstance = NULL;
if (bInParams)
{
hResult = pInParamsDefinition->SpawnInstance(0, &pInParamsInstance);
for (int i = 0; i < arguments.size(); i ++)
{
_variant_t varArg;
VariantCopy(&varArg, &(arguments[i].value));
hResult = pInParamsInstance->Put(_bstr_t(arguments[i].key), 0, &varArg, 0);
//hResult = pInParamsInstance->Put(_bstr_t(arguments[i].key), 0, &(arguments[i].value), 0);
}
}
IWbemClassObject* pOutParams = NULL;
hResult = pSvc->ExecMethod(bstrClassName, bstrMethodName, 0, NULL, pInParamsInstance, &pOutParams, NULL);
if (hResult != WBEM_S_NO_ERROR)
{
//pClass->Release();
if (pInParamsDefinition != NULL)
{
pInParamsDefinition->Release();
}
if (pOutParamsDefinition != NULL)
{
pOutParamsDefinition->Release();
}
if (pInParamsInstance != NULL)
{
pInParamsInstance->Release();
}
MyMessageBox_Error(_T("callStaticMethod"));
return NULL;
}
if (pInParamsDefinition != NULL)
{
pInParamsDefinition->Release();
}
if (pOutParamsDefinition != NULL)
{
pOutParamsDefinition->Release();
}
if (pInParamsInstance != NULL)
{
pInParamsInstance->Release();
}
if (bOutParams)
{
return pOutParams;
}
else
{
return NULL;
}
}
IWbemClassObject* ADWMISearch::callMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strInstancePath, CString strMethodName)
{
return callMethod(pSvc, pClass, strClassName, strInstancePath, strMethodName, vector<ADWMIParam>());
}
IWbemClassObject* ADWMISearch::callMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strInstancePath, CString strMethodName, vector<ADWMIParam> &arguments)
{
_bstr_t bstrClassName = _bstr_t(strClassName);
_bstr_t bstrMethodName = _bstr_t(strMethodName);
BOOL bInParams;
BOOL bOutParams;
HRESULT hResult;
//IWbemClassObject* pClass = getWMIClass(pSvc, strClassName);
IWbemClassObject* pInParamsDefinition = NULL;
IWbemClassObject* pOutParamsDefinition = NULL;
hResult = pClass->GetMethod(bstrMethodName, 0, &pInParamsDefinition, &pOutParamsDefinition);
if (hResult != WBEM_S_NO_ERROR)
{
//pClass->Release();
MyMessageBox_Error(_T("callMethod"));
return NULL;
}
if (pInParamsDefinition == NULL)
{
bInParams = FALSE;
}
else
{
bInParams = TRUE;
}
if (pOutParamsDefinition == NULL)
{
bOutParams = FALSE;
}
else
{
bOutParams = TRUE;
}
IWbemClassObject* pInParamsInstance = NULL;
if (bInParams)
{
hResult = pInParamsDefinition->SpawnInstance(0, &pInParamsInstance);
for (int i = 0; i < arguments.size(); i ++)
{
_variant_t varArg;
VariantCopy(&varArg, &(arguments[i].value));
hResult = pInParamsInstance->Put(_bstr_t(arguments[i].key), 0, &varArg, 0);
//hResult = pInParamsInstance->Put(_bstr_t(arguments[i].key), 0, &(arguments[i].value), 0);
}
}
IWbemClassObject* pOutParams = NULL;
hResult = pSvc->ExecMethod(_bstr_t(strInstancePath), bstrMethodName, 0, NULL, pInParamsInstance, &pOutParams, NULL);
if (hResult != WBEM_S_NO_ERROR)
{
//pClass->Release();
if (pInParamsDefinition != NULL)
{
pInParamsDefinition->Release();
}
if (pOutParamsDefinition != NULL)
{
pOutParamsDefinition->Release();
}
if (pInParamsInstance != NULL)
{
pInParamsInstance->Release();
}
MyMessageBox_Error(_T("callMethod"));
return NULL;
}
if (pInParamsDefinition != NULL)
{
pInParamsDefinition->Release();
}
if (pOutParamsDefinition != NULL)
{
pOutParamsDefinition->Release();
}
if (pInParamsInstance != NULL)
{
pInParamsInstance->Release();
}
if (bOutParams)
{
return pOutParams;
}
else
{
return NULL;
}
}
void ADWMISearch::disconnect(IWbemServices *pSvc)
{
pSvc->Release();
CoUninitialize();
}
ADWMISearch.h
#include <Wbemidl.h>
#include <vector>
#include <map>
using namespace std;
class ADWMIParam
{
public:
CString key;
_variant_t value;
public:
ADWMIParam(CString strKey, CString strValue)
{
key = strKey;
VariantInit(&value);
value.vt = VT_BSTR;
value.bstrVal = _bstr_t(strValue);
}
ADWMIParam(CString strKey, IWbemClassObject *pValue)
{
key = strKey;
VariantInit(&value);
value.vt = VT_UNKNOWN;
value.punkVal = pValue;
}
};
class ADWMISearch
{
public:
DWORD WIN32_FROM_HRESULT_alternate(HRESULT hr);
IWbemServices* connect(CString strServerName, CString strServerIP, CString strDomainName,
CString strUsername, CString strPassword);
vector<IWbemClassObject*> query(IWbemServices *pSvc, CString strDomainName, CString strPassword, CString strWQL);
CString getStringFromObject(IWbemClassObject* pObject, CString strPropertyName);
vector<CString> getStringsFromObjects(vector<IWbemClassObject*> npObjects, CString strPropertyName);
void clearObjects(vector<IWbemClassObject*> npObjects);
IWbemClassObject* getWMIClass(IWbemServices *pSvc, CString strClassName);
IWbemClassObject* getObjectFromObject(IWbemClassObject *pObject, CString strArgumentName);
IWbemClassObject* getObjectFromObjectWithCheck(IWbemClassObject *pOutParams, CString strArgumentName);
vector<ADWMIParam> genObjectArguments(CString strArgName, IWbemClassObject *pObject);
IWbemClassObject* callStaticMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strMethodName);
IWbemClassObject* callStaticMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strMethodName, vector<ADWMIParam> &arguments);
IWbemClassObject* callMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strInstancePath, CString strMethodName);
IWbemClassObject* callMethod(IWbemServices *pSvc, IWbemClassObject *pClass, CString strClassName,
CString strInstancePath, CString strMethodName, vector<ADWMIParam> &arguments);
void disconnect(IWbemServices *pSvc);
};
the call code(a place like main is ok)
ADWMISearch *wmiSearcher = new ADWMISearch();
IWbemServices *pSvc = wmiSearcher->connect("luo-pc", "127.0.0.1", "", "", "");
IWbemClassObject *pLSSSClass = wmiSearcher->getWMIClass(pSvc, "Win32_LogicalShareSecuritySetting");
vector<IWbemClassObject*> npObjects = wmiSearcher->query(pSvc, "", "", "Select * from Win32_Log
When I connect my embedded device to my system, I am running my program which will write to the port my embedded is connect and it prints the reply to console.
When I connect my device and run this program it is not giving any output.
But when I connect my device and use PUTTY to send some commands first and then run my program it is working.
Maybe there is a problem in the way I am starting communication?
My source code is:
#include "stdafx.h"
#include <iostream>
//#include <windows.h>
#include <afx.h>
int main()
{
using namespace std;
int i=0;
// cout << "Hello world!" << endl;
HANDLE hSerial;
hSerial = CreateFile("COM5",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE)
{
if(GetLastError()==ERROR_FILE_NOT_FOUND)
{
// TRACE("serial port does not exist for reading\n");
//serial port does not exist. Inform user.
}
// TRACE("some other error,serial port does not exist for reading\n");
//some other error occurred. Inform user.
}
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams))
{
// TRACE("error getting state for reading\n");
//error getting state
}
dcbSerialParams.BaudRate=9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams))
{
//TRACE("error setting state for reading\n");
//error setting serial port state
}
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts))
{
// TRACE("some error occured for reading\n");
//error occureed. Inform user
}
int n=100,n1=100;
char szBuff[100];
DWORD dwBytesRead = 0;
char szBuff1[100];
DWORD dwByteswrote = 0;
memset(szBuff1,0,100);
memcpy(szBuff1,"LIST\r",5);
if(!WriteFile(hSerial, szBuff1,5, &dwByteswrote, NULL))
{
cout << "error writing" ;
}
cout << szBuff1 << endl;
cout << dwByteswrote << endl;
while(1)
{
if(!ReadFile(hSerial, szBuff, n1, &dwBytesRead, NULL))
{
cout << "error reading";
break;
}
else
{
cout << dwBytesRead << endl;
szBuff[dwBytesRead]='\0';
if(dwBytesRead>0)
{
cout << (szBuff);
break;
}
}
}
cin >> i;
}
Try this... you will probably need to do the code for exceptions (ex: if the response is bigger than 2024)
bool SendModemATCommand(const string &strCommand, int iModemPort, string &strRetValue)
{
bool bRetValue = false;
strRetValue = "";
char cBuffer[2024];
HANDLE hCom = NULL;
char cComPort[64];
sprintf_s(cComPort,"\\\\.\\COM%d", iModemPort);
hCom = CreateFile( cComPort,
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (hCom != INVALID_HANDLE_VALUE)
{
COMMTIMEOUTS comTimeOuts;
comTimeOuts.ReadIntervalTimeout = MAXDWORD;
comTimeOuts.ReadTotalTimeoutMultiplier = MAXDWORD;
comTimeOuts.ReadTotalTimeoutConstant = 0;//MAXDWORD;
comTimeOuts.WriteTotalTimeoutMultiplier = 0;
comTimeOuts.WriteTotalTimeoutConstant = 0;
if(SetCommTimeouts(hCom, &comTimeOuts))
{
DCB dcb;
dcb.DCBlength = sizeof(DCB);
if(GetCommState(hCom, &dcb))
{
DWORD dwBytesWritten = 0;
DWORD dwBytesRead = 0;
DWORD dwBytesTotal = 0;
if( WriteFile(hCom, strCommand.c_str(), (int)strCommand.size(), &dwBytesWritten, NULL) )
{
if(dwBytesWritten == strCommand.size())
{
dwBytesRead = 0;
DWORD tickStart = GetTickCount();
bool bTimeOut = false;
while(true)
{
while(ReadFile(hCom, cBuffer + dwBytesTotal, 1, &dwBytesRead, NULL))
{
if(dwBytesRead == 0 && dwBytesTotal != dwBytesWritten)
break;
dwBytesTotal += dwBytesRead;
}
if ( dwBytesTotal == 0 )
{
// timeout
if ( GetTickCount() - tickStart > 10000) // 10 Seconds
{
bTimeOut = true;
break;
}
}
else
break;
}
cBuffer[dwBytesTotal] = '\0';
strRetValue = cBuffer;
if(bTimeOut)
strRetValue = "Timed out:" + strCommand;
else
bRetValue = true;
}
}
}
}
CloseHandle(hCom);
}
return bRetValue;
}
Most likely the problem is with your initialization.
I recall having this type of trouble before and Com Timeouts structure was particularly troublesome.
I suggest you get a null modem cable from COM5 to another port on the machine (if you have one), or to another computer. Then use a terminal program to open up the other port and see you can see the "List" command coming through when you run the program. If not then it's very likely to be related to the way you are initializing & opening the com port.
This link may prove useful. Just strip out the Afx stuff and look particularly at the initialization.
http://www.codeproject.com/KB/system/chaiyasit_t.aspx
One other suggestion, you only send List once. If the device is not already plugged in and ready, nothing will happen. Maybe it should keep sending the list command until it gets a
Response.
Also, do you need "List\r\n" or just "List\r"? What is the other ends expecting?
I am working on an embeeded device.i connect to it using COM port.
It gives the list of all files when i send a command "LIST" to it.
so i wrote an "hello world" which will connect to the port device is connected and will send data.
When i connect my device and run my program it is writing to the port and not receiving any bytes from the port.
but when i open the COM port using PUTTY(which is used to open port and send some data) and send COMMAND it works and when i CLOSE PUTTY and NOW RUN MY PROGRAM now it is working fine,so i need to OPEN port with putty for the first time for my program to work.
may be i am not initialising some functions...:(
can anyone help me out in this,i am unable to find solution for the past day.thanks in advance...
my source code is:-
#include "stdafx.h"
#include <iostream>
#include <afx.h>
int main()
{
using namespace std;
int i=0;
// cout << "Hello world!" << endl;
HANDLE hSerial;
hSerial = CreateFile("COM5",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE)
{
if(GetLastError()==ERROR_FILE_NOT_FOUND)
{
// TRACE("serial port does not exist for reading\n");
//serial port does not exist. Inform user.
}
// TRACE("some other error,serial port does not exist for reading\n");
//some other error occurred. Inform user.
}
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams))
{
// TRACE("error getting state for reading\n");
//error getting state
}
dcbSerialParams.BaudRate=9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
dcbSerialParams.fOutX=TRUE;
dcbSerialParams.fInX=TRUE;
if(!SetCommState(hSerial, &dcbSerialParams))
{
//TRACE("error setting state for reading\n");
//error setting serial port state
}
COMMTIMEOUTS timeouts={0};
timeouts.ReadIntervalTimeout=50;
timeouts.ReadTotalTimeoutConstant=50;
timeouts.ReadTotalTimeoutMultiplier=10;
timeouts.WriteTotalTimeoutConstant=50;
timeouts.WriteTotalTimeoutMultiplier=10;
if(!SetCommTimeouts(hSerial, &timeouts))
{
// TRACE("some error occured for reading\n");
//error occureed. Inform user
}
int n=100,n1=100;
char szBuff[100];
DWORD dwBytesRead = 0;
char szBuff1[100];
DWORD dwByteswrote = 0;
memset(szBuff1,0,100);
memcpy(szBuff1,"LIST\r",5);
FlushFileBuffers(hSerial);
LPDWORD uf=0;
GetCommModemStatus(hSerial,uf);
TRACE("%d\n",uf);
if(!WriteFile(hSerial, szBuff1,5, &dwByteswrote, NULL))
{
cout << "error writing" ;
}
cout << szBuff1 << endl;
cout << dwByteswrote << endl;
dwByteswrote=0;
while(1)
{
if(!ReadFile(hSerial, szBuff, n1, &dwBytesRead, NULL))
{
cout << "error reading";
break;
}
else
{
cout << dwBytesRead << endl;
szBuff[dwBytesRead]='\0';
if(dwBytesRead>0)
{
cout << (szBuff);
break;
}
else
{
}
}
}
cin >> i;
}
You might try setting all the DCB options and clearing port errors
// Common settings
dcbSerialParams.DCBlength = sizeof( dcbSerialParams );
dcbSerialParams.ByteSize = 8;
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.fParity = FALSE;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.fDtrControl = 0;
dcbSerialParams.fRtsControl = 0;
// If you say so
dcbSerialParams.fOutX = TRUE;
dcbSerialParams.fInX = TRUE;
// Not so common settings
dcbSerialParams.fBinary = FALSE;
dcbSerialParams.fParity = FALSE;
dcbSerialParams.fOutxCtsFlow = FALSE;
dcbSerialParams.fOutxDsrFlow = FALSE;
dcbSerialParams.fDsrSensitivity = FALSE;
dcbSerialParams.fErrorChar = FALSE;
dcbSerialParams.fNull = FALSE;
dcbSerialParams.fAbortOnError = FALSE;
// Clear errors
unsigned long ulCommErr = 0;
ClearCommBreak( hSerial );
ClearCommError( hSerial, &ulCommErr, NULL );
Probably unrelated, but I noticed I at some point added a security descriptor to CreateFile() in my serial code, I believe some configuration of Windows Server required it.
// Allow access
SECURITY_ATTRIBUTES sa, *pSa = NULL;
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = (SECURITY_DESCRIPTOR*)LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
if ( sa.lpSecurityDescriptor
&& InitializeSecurityDescriptor( (SECURITY_DESCRIPTOR*)sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION )
&& SetSecurityDescriptorDacl( (SECURITY_DESCRIPTOR*)sa.lpSecurityDescriptor, TRUE, (PACL)NULL, FALSE ) )
pSa = &sa;
// Open the port
hSerial = CreateFile( x_pPort,
GENERIC_READ | GENERIC_WRITE,
0,
pSa,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( pSa )
LocalFree( pSa->lpSecurityDescriptor );
MSDN documentation of CreateFile demands using 0 as dwShareMode for Communications Resources like COM ports (you use FILE_SHARE_WRITE|FILE_SHARE_READ). Try this first. Even if it won't help it is better to follow the official documentation anyway.
If (1) doesn't work then try using CREATE_ALWAYS instead of OPEN_EXISTING. Actually OPEN_EXISTING is demanded by the documentation but one community message (on the same page after the official documentation) suggests using CREATE_ALWAYS for LPT ports (may be it is different though).
The following code fails when ExecMethod is called. Can anyone pinpoint what I am doing wrong?
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
int main(int iArgCnt, char ** argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you must specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object. "
<< "Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the local root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\wmi"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels for the proxy ------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set up to call the WmiSetBrightness Method
BSTR MethodName = SysAllocString(L"WmiSetBrightness");
BSTR ClassName = SysAllocString(L"WmiMonitorBrightnessMethods");
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0,
&pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
VARIANT var1;
VariantInit(&var1);
V_VT(&var1) = VT_BSTR;
V_BSTR(&var1) = SysAllocString(L"1000");
hres = pClassInstance->Put(L"Timeout", 0, &var1, CIM_UINT32); //CIM_UINT64
VARIANT var2;
VariantInit(&var2);
V_VT(&var2) = VT_BSTR;
V_BSTR(&var2) = SysAllocString(L"30");
hres = pClassInstance->Put(L"Brightness", 0, &var2, CIM_UINT8);
// Execute Method
IWbemClassObject* pOutParams = NULL;
hres = pSvc->ExecMethod(ClassName, MethodName, 0,
NULL, pClassInstance, &pOutParams, NULL);
if (FAILED(hres))
{
cout << "Could not execute method. Error code = 0x"
<< hex << hres << endl;
//VariantClear(&varCommand);
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pInParamsDefinition->Release();
pOutParams->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// To see what the method returned,
// use the following code. The return value will
// be in &varReturnValue
VARIANT varReturnValue;
hres = pOutParams->Get(_bstr_t(L"ReturnValue"), 0,
&varReturnValue, NULL, 0);
// Clean up
//--------------------------
// VariantClear(&varCommand);
VariantClear(&varReturnValue);
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pInParamsDefinition->Release();
pOutParams->Release();
pLoc->Release();
pSvc->Release();
CoUninitialize();
return 0;
}
Since the question was tagged "C++" I tidied up your code by using C++ techniques for failure checking and cleanup. It turned out that you've forgotten to check for failure in several places. The code below reports first failure at GetObject(className, ...).
#define _WIN32_DCOM
#pragma comment(lib, "wbemuuid.lib")
#include <iostream>
#include <string>
#include <stdexcept>
#include <stdlib.h> // EXIT_FAILURE, EXIT_SUCCESS
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#define DEF_SMARTPTR_TYPE( Interface ) \
_COM_SMARTPTR_TYPEDEF( Interface, __uuidof( Interface ) )
DEF_SMARTPTR_TYPE( IWbemLocator );
DEF_SMARTPTR_TYPE( IWbemServices );
DEF_SMARTPTR_TYPE( IWbemClassObject );
bool throwX( string const& s ) { throw std::runtime_error( s ); }
string hexFrom( unsigned long v )
{
char buf[40];
sprintf( buf, "%08lx", v );
return buf;
}
struct Fail
{
string message;
explicit Fail( string const& aMessage ): message( aMessage ) {}
};
void operator ||( HRESULT hr, Fail const& failure )
{
SUCCEEDED( hr )
|| throwX( failure.message + " (Error code 0x" + hexFrom( hr ) + ")" );
}
struct ComLibUsage
{
struct Threading
{
enum Enum {
singleThreaded = COINIT_APARTMENTTHREADED,
multiThreaded = COINIT_MULTITHREADED
};
};
ComLibUsage( Threading::Enum threading = Threading::multiThreaded )
{
::CoInitializeEx( 0, threading )
|| Fail( "Failed to initialize COM library." );
}
~ComLibUsage() { ::CoUninitialize(); }
};
void cppMain()
{
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
ComLibUsage comLibUsage( ComLibUsage::Threading::multiThreaded );
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you must specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
) || Fail( "Failed to initialize security" );
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocatorPtr pLoc;
CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc
) || Fail( "Failed to create IWbemLocator object." );
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
// Connect to the local root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
IWbemServicesPtr pSvc;
pLoc->ConnectServer(
_bstr_t(L"ROOT\\wmi"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
) || Fail( "Could not connect." );
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels for the proxy ------------------------
CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
) || Fail( "Could not set proxy blanket" );
////////////////////////////////////////////////////////////////
// set up to call the WmiSetBrightness Method
_bstr_t methodName = L"WmiSetBrightness";
_bstr_t className = L"WmiMonitorBrightnessMethods";
IWbemClassObjectPtr pClass;
pSvc->GetObject(className, 0, NULL, &pClass, NULL)
|| Fail( "GetObject(className, ...) failed" );
IWbemClassObjectPtr pInParamsDefinition;
pClass->GetMethod(methodName, 0, &pInParamsDefinition, NULL)
|| Fail( "GetMethod(methodName, ...) failed" );
IWbemClassObjectPtr pClassInstance;
pInParamsDefinition->SpawnInstance(0, &pClassInstance)
|| Fail( "SpawnInstance failed" );
_variant_t var1( L"1000" );
pClassInstance->Put(L"Timeout", 0, &var1, CIM_UINT32) //CIM_UINT64
|| Fail( "Put failed for 'Timeout'" );
_variant_t var2( L"30" );
pClassInstance->Put(L"Brightness", 0, &var2, CIM_UINT8)
|| Fail( "Put failed for 'Brightness'" );
// Execute Method
IWbemClassObject* pOutParams = NULL;
//hres = pSvc->ExecMethod(className, methodName, 0,
//NULL, pClassInstance, &pOutParams, NULL)
//|| Fail( "Could not execute method" );
// To see what the method returned,
// use the following code. The return value will
// be in &varReturnValue
_variant_t varReturnValue;
pOutParams->Get(_bstr_t(L"ReturnValue"), 0, &varReturnValue, NULL, 0)
|| Fail( "Get failed" );
}
int main()
{
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
Cheers & hth. (even if it's a bit on the side of your question!),
Instead of the Step 4 & 6 from Example: Calling a Provider Method, it can set the brightness ABSOLUTELY.
Step 4:
IWbemServices *pSvc = NULL;
// Connect to the local root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\WMI"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\WMI WMI namespace" << endl;
Step 6:
BSTR ClassName = SysAllocString(L"WmiMonitorBrightnessMethods");
BSTR MethodName = SysAllocString(L"WmiSetBrightness");
BSTR bstrQuery = SysAllocString(L"Select * from WmiMonitorBrightnessMethods");
IEnumWbemClassObject *pEnum = NULL;
hres = pSvc->ExecQuery(_bstr_t(L"WQL"), //Query Language
bstrQuery, //Query to Execute
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, //Make a semi-synchronous call
NULL, //Context
&pEnum /*Enumeration Interface*/);
hres = WBEM_S_NO_ERROR;
ULONG ulReturned;
IWbemClassObject *pObj;
DWORD retVal = 0;
//Get the Next Object from the collection
hres = pEnum->Next(WBEM_INFINITE, //Timeout
1, //No of objects requested
&pObj, //Returned Object
&ulReturned /*No of object returned*/);
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
VARIANT var1;
VariantInit(&var1);
BSTR ArgName0 = SysAllocString(L"Timeout");
V_VT(&var1) = VT_BSTR;
V_BSTR(&var1) = SysAllocString(L"0");
hres = pClassInstance->Put(ArgName0,
0,
&var1,
CIM_UINT32); //CIM_UINT64
printf("\nPut ArgName0 returned 0x%x:", hres);
VariantClear(&var1);
VARIANT var;
VariantInit(&var);
BSTR ArgName1 = SysAllocString(L"Brightness");
V_VT(&var2) = VT_BSTR;
V_BSTR(&var2) = SysAllocString(L"80"); //Brightness value
hres = pClassInstance->Put(ArgName1,
0,
&var2,
CIM_UINT8);
VariantClear(&var2);
printf("\nPut ArgName1 returned 0x%x:", hres);
// Call the method
VARIANT pathVariable;
VariantInit(&pathVariable);
hres = pObj->Get(_bstr_t(L"__PATH"),
0,
&pathVariable,
NULL,
NULL);
printf("\npObj Get returned 0x%x:", hres);
hres = pSvc->ExecMethod(pathVariable.bstrVal,
MethodName,
0,
NULL,
pClassInstance,
NULL,
NULL);
VariantClear(&pathVariable);
printf("\nExecMethod returned 0x%x:", hres);
printf("Terminating normally\n");
// Clean up
//--------------------------
//VariantClear(&varCommand);
//VariantClear(&varReturnValue);
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pClassInstance->Release();
pInParamsDefinition->Release();
//pOutParams->Release();
pLoc->Release();
pSvc->Release();
CoUninitialize();
system("pause");
return 0;
ref: 通过WMI的方式去设置LCD背光亮度 Author: Tody