On Windows XP there is a known way to create a Remote Assistance Ticket.
http://msdn.microsoft.com/en-us/library/ms811079.aspx
But on Vista this does not appear to work. How does one do this on Vista or Windows 7?
There turns out to be two ways. The Microsoft API is called IRASrv and is documented here:
http://msdn.microsoft.com/en-us/library/cc240176(PROT.10).aspx
Another way is to simply call msra.exe. with password and novice params (e.g. msra.exe /saveasfile testfile thepassword). However that does prompt the user with the password dialog.
Here is example code for calling the IRASrv interface and generating a Remote Assistance Connection String.
COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
HRESULT hr = S_OK;
BSTR bstrUserName = SysAllocString(L"jon");
BSTR bstrDomainName = SysAllocString(L"");
BSTR bstrPasswordStr = SysAllocString(L"testpass");
// Get the security information entered by the user
_bstr_t bstrUser(bstrUserName);
_bstr_t bstrDomain(bstrDomainName);
_bstr_t bstrPassword(bstrPasswordStr);
// Set AuthIdentity
SEC_WINNT_AUTH_IDENTITY_W AuthIdentity = {
(unsigned short*)bstrUserName,
bstrUser.length(),
(unsigned short*)bstrDomainName,
bstrDomain.length(),
(unsigned short*)bstrPasswordStr,
bstrPassword.length(),
SEC_WINNT_AUTH_IDENTITY_UNICODE
};
COAUTHINFO AuthInfo = {
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_DEFAULT,
NULL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // The authentication level used
RPC_C_IMP_LEVEL_IMPERSONATE,
(COAUTHIDENTITY*)&AuthIdentity,
EOAC_NONE
};
si.pAuthInfo = &AuthInfo;
si.pwszName = bstrMachineName;
qi.pIID = &(__uuidof(RAServerLib::IRASrv));
hr = ::CoCreateInstanceEx(
__uuidof(RAServerLib::RASrv), NULL, CLSCTX_REMOTE_SERVER,
&si, 1, &qi );
if (FAILED(hr))
{
return hr;
}
CComPtr<RAServerLib::IRASrv> prasrv;
hr = qi.pItf->QueryInterface(__uuidof(RAServerLib::IRASrv), (void**)&prasrv);
if (FAILED(hr))
{
return hr;
}
LPWSTR pstr=NULL;
hr = prasrv->raw_GetNoviceUserInfo(&pstr);
if (FAILED(hr))
{
return hr;
}
pstr contains the Remote Assistance Connection String (type 2)
Related
I have the following code (main part taken from MS SDK v7.1 Sample code, which demonstrates how to start an non-elevated process from an elevated one)-
The elevated and non-elevated process will be started on an (unsupervised) server, so user interaction is a no-go (except for the configuring part, if needed, of course).
The problem is, that the non-elevated process started through IShellDispatch2->ShellExecute is still elevated (expected was to be non-elevated).
This was confirmed by using IsUserAnAdmin() API.
Any ideas why the process created through ShellExecute() does have still elevated rights?
Some more relevant details: on my machine UAC is disabled.
The VS 2013 based application is manifested:
)
(manifesting can be disabled with /MANIFEST:no linker flag, if it will help in solving this).
I'm compiling it on Windows 7 x64 using VS 2013.
#include <shlwapi.h>
#include <shlobj.h>
#include <comutil.h>
#pragma comment(lib, "shlwapi.lib")
// link with (at least) OleAut32.lib shlwapi.lib comsupp.lib shell32.lib uuid.lib
// sorry for the bad formatting
int main(void)
{
std::wstring processName(L"myapp.exe"), processParams(L"-myAppParam");
LPWSTR processNamePtr = const_cast<LPWSTR>(processName.c_str());
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IShellView *psv;
HRESULT hr = GetShellViewForDesktop(IID_PPV_ARGS(&psv));
if (SUCCEEDED(hr))
{
IShellDispatch2 *psd;
hr = GetShellDispatchFromView(psv, IID_PPV_ARGS(&psd));
if (SUCCEEDED(hr))
{
BSTR bstrProcessName = SysAllocString(processNamePtr);
hr = bstrProcessName ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
VARIANT vtEmpty = {}; // VT_EMPTY
LPWSTR processParamsPtr = const_cast<LPWSTR>(processParams.c_str());
_bstr_t bstrProcessParams(processParamsPtr);
VARIANT varParams;
varParams.vt = VT_BSTR;
varParams.bstrVal = bstrProcessParams;
char processDir[MAX_PATH + 1];
::GetCurrentDirectory(MAX_PATH, processDir);
_bstr_t bstrProcessDir(processDir);
VARIANT varProcessDir;
varProcessDir.vt = VT_BSTR;
varProcessDir.bstrVal = bstrProcessDir;
_bstr_t bstrOperation("open");
VARIANT varOperation;
varOperation.vt = VT_BSTR;
varOperation.bstrVal = bstrOperation;
hr = psd->ShellExecute(bstrProcessName,
varParams, // reinterpret_cast<_variant_t&>(bstrProcessParams),
varProcessDir,
varOperation,
vtEmpty);
SysFreeString(bstrProcessName);
SysFreeString(bstrProcessParams);
}
psd->Release();
}
psv->Release();
}
CoUninitialize();
}
} // main()
// use the shell view for the desktop using the shell windows automation to find the
// desktop web browser and then grabs its view
//
// returns:
// IShellView, IFolderView and related interfaces
HRESULT GetShellViewForDesktop(REFIID riid, void **ppv)
{
*ppv = NULL;
IShellWindows *psw;
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
if (SUCCEEDED(hr))
{
HWND hwnd;
IDispatch* pdisp;
VARIANT vEmpty = {}; // VT_EMPTY
if (S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp))
{
IShellBrowser *psb;
hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
if (SUCCEEDED(hr))
{
IShellView *psv;
hr = psb->QueryActiveShellView(&psv);
if (SUCCEEDED(hr))
{
hr = psv->QueryInterface(riid, ppv);
psv->Release();
}
psb->Release();
}
pdisp->Release();
}
else
{
hr = E_FAIL;
}
psw->Release();
}
return hr;
} // GetShellViewForDesktop()
// From a shell view object gets its automation interface and from that gets the shell
// application object that implements IShellDispatch2 and related interfaces.
HRESULT GetShellDispatchFromView(IShellView *psv, REFIID riid, void **ppv)
{
*ppv = NULL;
IDispatch *pdispBackground;
HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
if (SUCCEEDED(hr))
{
IShellFolderViewDual *psfvd;
hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
if (SUCCEEDED(hr))
{
IDispatch *pdisp;
hr = psfvd->get_Application(&pdisp);
if (SUCCEEDED(hr))
{
hr = pdisp->QueryInterface(riid, ppv);
pdisp->Release();
}
psfvd->Release();
}
pdispBackground->Release();
}
return hr;
} // GetShellDispatchFromView()
On my machine UAC is disabled.
Right there is your problem. By disabling UAC you stop the system from creating processes as standard user. If the logged on user is an administrator, then processes run with a fully privileged token.
With UAC disabled, the explorer process that runs the shell is started using the full token of the interactive user, which it seems is the token of an admin user. And so when the shell starts a new process with IShellDispatch2->ShellExecute that new process runs under the same user token.
You'll need to enable UAC to allow the system to create processes with standard user tokens. When you enable UAC, the shell's explorer process will run as standard user and so IShellDispatch2->ShellExecute will create new processes running as standard user.
I am trying to write an application for applying for a certificate and revoking it with code.
By referring to the msdn, I implemented the Applying Certification part with ICertRequest3 interface, and the Revoking part with ICertAdmin2::RevokeCertificate interface.
Here is the problem, it requires serial number of a certificate for ICertAdmin2::RevokeCertificate to get to work and I do not know how to get the serial number property
of the certificate issued by the CA.
Specifically speaking, what I need is to find a way to extract the serial number property of the certificate issued by the CA after I submit the request with ICertRequest3.
For your information, below is the code snippet for applying and revoking certificate.
HRESULT enrollWithICertRequest3(
X509CertificateEnrollmentContext context,
LPCWSTR template_name,
X509EnrollmentAuthFlags policy_server_authtype,
LPCWSTR policy_server_url,
LPCWSTR policy_server_username,
LPCWSTR policy_server_password,
X509EnrollmentAuthFlags enrollment_server_authtype,
LPCWSTR enrollment_server_url,
LPCWSTR enrollment_server_username,
LPCWSTR enrollment_server_password,
BSTR *cert_base64)
{
HRESULT hr = S_OK;
BSTR bstr_template_name = NULL;
BSTR bstr_policyserver_url = NULL;
BSTR bstr_policyserver_id = NULL;
BSTR bstr_policyserver_username = NULL;
BSTR bstr_policyserver_password = NULL;
IX509EnrollmentPolicyServer *policyserver_interface = NULL;
IX509CertificateTemplates *templates_interface = NULL;
IX509CertificateTemplate *template_interface = NULL;
IX509Enrollment2 *enroll2_interface = NULL;
BSTR bstrRequest = NULL;
BSTR bstrEnrollmentServerUrl = NULL;
BSTR bstrEnrollmentServerUsername = NULL;
BSTR bstrEnrollmentServerPassword = NULL;
ICertRequest3 *request3_interface = NULL;
LONG disposition = 0;
BSTR bstr_disposition = NULL;
VARIANT var_fullresponse;
VariantInit(&var_fullresponse);
var_fullresponse.vt = VT_BSTR;
var_fullresponse.bstrVal = NULL;
bstr_template_name = SysAllocString(template_name);
bstr_policyserver_url = SysAllocString(policy_server_url);
if(!bstr_template_name && template_name ||
!bstr_policyserver_url && policy_server_url)
{
hr = E_OUTOFMEMORY;
goto error;
}
if(policy_server_authtype == X509AuthUsername)
{
bstr_policyserver_username = SysAllocString(policy_server_username);
bstr_policyserver_password = SysAllocString(policy_server_password);
if(!bstr_policyserver_username && policy_server_username ||
!bstr_policyserver_password && policy_server_password)
{
hr = E_OUTOFMEMORY;
goto error;
}
}
else if(policy_server_authtype == X509AuthCertificate)
{
//This call is preparation of the call to pPolicyServer->SetCredential.
//For certificate authentication, bstrPolicyServerUsername should be a
//pointer to a memory blob in which certificate hash value is stored.
hr = hex2BstrByte(policy_server_username, &bstr_policyserver_username);
if(FAILED(hr))
goto error;
}
hr = CoCreateInstance(
__uuidof(CX509EnrollmentPolicyWebService),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509EnrollmentPolicyServer),
(void **)&policyserver_interface);
if(FAILED(hr))
goto error;
//The bstrPolicyServerId is optional
hr = policyserver_interface->Initialize(
bstr_policyserver_url, //[in] BSTR bstrPolicyServerUrl
NULL, //[in] BSTR bstrPolicyServerId
policy_server_authtype, //[in] X509EnrollmentAuthFlags authFlags
false, //[in] VARIANT_BOOL fIsUnTrusted
context); //[in] X509CertificateEnrollmentContext context
if(FAILED(hr))
goto error;
//This call sets authentication type and authentication credential
//to policy server to the object pointed by pPolicyServer.
//This call is necessary even for Kerberos authentication type.
hr = policyserver_interface->SetCredential(
NULL, //[in] LONG hWndParent
policy_server_authtype, //[in] X509EnrollmentAuthFlags flag
bstr_policyserver_username, //[in] BSTR strCredential
bstr_policyserver_password); //[in] BSTR strPassword
if(FAILED(hr))
goto error;
//The flag LoadOptionDefault means enrollment process reads
//policies (templates) from local cache in file system if it exists.
//Otherwise, it queries policies (templates) from policy server through
//http protocol, then caches them in local file system.
//The flag LoadOptionReload queries policies (templates) directly from
//policy server regardless of if cached policies (templates) exist.
hr = policyserver_interface->LoadPolicy(LoadOptionDefault); //[in] X509EnrollmentPolicyLoadOption option
if(FAILED(hr))
goto error;
//pTemplates points to collection of policies (templates)
hr = policyserver_interface->GetTemplates(&templates_interface);
if(FAILED(hr))
goto error;
//pTemplate points to the policy (template) specified by a template name
hr = templates_interface->get_ItemByName(bstr_template_name, &template_interface);
if(FAILED(hr))
goto error;
//This call is preparation of the call IX509Enrollment2::InstallResponse2
hr = policyserver_interface->GetPolicyServerId(&bstr_policyserver_id);
if(FAILED(hr))
goto error;
hr = CoCreateInstance(
__uuidof(CX509Enrollment),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509Enrollment2),
(void **) &enroll2_interface);
if(FAILED(hr))
goto error;
//This is a new API in Windows 7 to support http protocol
hr = enroll2_interface->InitializeFromTemplate(
context, //[in] X509CertificateEnrollmentContext context
policyserver_interface, //[in] IX509EnrollmentPolicyServer *pPolicyServer
template_interface); //[in] IX509CertificateTemplate *pTemplate
if(FAILED(hr))
goto error;
//Get request blob for the call ICertRequest3::Submit
hr = enroll2_interface->CreateRequest(
XCN_CRYPT_STRING_BASE64,
&bstrRequest);
if(FAILED(hr))
goto error;
hr = CoCreateInstance(
__uuidof(CCertRequest),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ICertRequest3),
(void **) &request3_interface);
if(FAILED(hr))
goto error;
bstrEnrollmentServerUrl = SysAllocString(enrollment_server_url);
if(!bstrEnrollmentServerUrl && enrollment_server_url)
{
hr = E_OUTOFMEMORY;
goto error;
}
if(enrollment_server_authtype == X509AuthUsername)
{
bstrEnrollmentServerUsername = SysAllocString(enrollment_server_username);
bstrEnrollmentServerPassword = SysAllocString(enrollment_server_password);
if(!bstrEnrollmentServerUsername && enrollment_server_username ||
!bstrEnrollmentServerPassword && enrollment_server_password)
{
hr = E_OUTOFMEMORY;
goto error;
}
}
else if(enrollment_server_authtype == X509AuthCertificate)
{
//This call is preparation of the call to pCertRequest3->SetCredential.
//For certificate authentication, bstrPolicyServerUsername should be a
//pointer to a memory blob in which certificate hash value is stored.
hr = hex2BstrByte(enrollment_server_username, &bstrEnrollmentServerUsername);
if(FAILED(hr))
goto error;
}
//This call sets authentication type and authentication credential
//to enrollment server to the object pointed by pCertRequest3.
//This call is necessary even for Kerberos authentication type.
hr = request3_interface->SetCredential(
NULL, //[in] LONG hWnd
enrollment_server_authtype, //[in] X509EnrollmentAuthFlags AuthType
bstrEnrollmentServerUsername, //[in] BSTR strCredential
bstrEnrollmentServerPassword); //[in] BSTR strPassword
if(FAILED(hr))
goto error;
//Submit request and get response
//For ICertRequest3::Submit, bstrConfig can be
//enrollment server URL
hr = request3_interface->Submit(
CR_IN_BASE64 | CR_IN_FORMATANY, //[in] LONG Flags
bstrRequest, //[in] BSTR const strRequest
NULL, //[in] BSTR const strAttributes
bstrEnrollmentServerUrl, //[in] BSTR const strConfig
&disposition); //[out, retval] LONG *pDisposition
if(FAILED(hr))
goto error;
//Check the submission status
if(disposition != CR_DISP_ISSUED) //Not enrolled
{
hr = request3_interface->GetDispositionMessage(&bstr_disposition);
if(FAILED(hr))
goto error;
request3_interface->GetLastStatus(&hr);
if(disposition == CR_DISP_UNDER_SUBMISSION) //Pending
{
wprintf(L"The submission is in pending status: %s \n", bstr_disposition);
goto error;
}
else //Failed
{
wprintf(L"The submission failed: %s \n", bstr_disposition);
goto error;
}
}
// Get the issued certificate
hr = request3_interface->GetCertificate(CR_OUT_BASE64, cert_base64);
if(FAILED(hr))
goto error;
////Get full response for installation
//hr = request3_interface->GetFullResponseProperty(
// FR_PROP_FULLRESPONSENOPKCS7, //[in] LONG PropId (FR_PROP_*)
// 0, //[in] LONG PropIndex
// PROPTYPE_BINARY, //[in] LONG PropType (PROPTYPE_*
// CR_OUT_BASE64, //[in] LONG Flags (CR_OUT_*)
// &var_fullresponse); //[out, retval] VARIANT *pvarPropertyValue
//if(FAILED(hr))
// goto error;
////Install the response
//hr = enroll2_interface->InstallResponse2(
// AllowNone, //[in] InstallResponseRestrictionFlags Restrictions
// var_fullresponse.bstrVal, //[in] BSTR strResponse
// XCN_CRYPT_STRING_BASE64, //[in] EnrodingType Encoding
// bstr_policyserver_password, //[in] BSTR strPassword
// bstr_policyserver_url, //[in] BSTR strEnrollmentPolicyServerUrl
// bstr_policyserver_id, //[in] BSTR strEnrollmentPolicyServerID
// PsfNone, //[in] PolicyServerUrlFlags EnrollmentPolicyServerFlags
// policy_server_authtype); //[in] X509EnrollmentAuthFlags authFlags
//if(FAILED(hr))
// goto error
/*BSTR pwd = SysAllocString(L"tOngbupan");
hr = enroll2_interface->CreatePFX(pwd, PFXExportEEOnly, XCN_CRYPT_STRING_BASE64, cert_base64);
SysFreeString(pwd);*/
error:
SysFreeString(bstr_template_name);
SysFreeString(bstr_policyserver_url);
SysFreeString(bstr_policyserver_id);
SysFreeString(bstr_policyserver_username);
SysFreeString(bstr_policyserver_password);
SysFreeString(bstr_disposition);
SysFreeString(bstrEnrollmentServerUrl);
SysFreeString(bstrEnrollmentServerPassword);
SysFreeString(bstrEnrollmentServerUsername);
SysFreeString(bstrRequest);
if(!var_fullresponse.bstrVal)
VariantClear(&var_fullresponse);
if(policyserver_interface)
policyserver_interface->Release();
if(templates_interface)
templates_interface->Release();
if(request3_interface)
request3_interface->Release();
if(template_interface)
template_interface->Release();
if(enroll2_interface)
enroll2_interface->Release();
return hr;
}
bool revokeUserCert(const wstring& cert_serial_num)
{
BSTR bstrSerial = NULL; // certificate serial number
HRESULT hr;
LONG nDisp;
ICertAdmin2* pCertAdmin = NULL;
bstrSerial = SysAllocString(cert_serial_num.c_str());
hr = CoCreateInstance(
CLSID_CCertAdmin,
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
IID_ICertAdmin2,
(void **) &pCertAdmin);
if(FAILED(hr))
{
printf("init icertadmin error\n");
goto error;
}
ICertConfig* pCertConfig = NULL;
BSTR strCAConfig = NULL;
// Create ICertConfig
hr = CoCreateInstance(
__uuidof(CCertConfig),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ICertConfig),
(void**)&pCertConfig);
// Get CA config
hr = pCertConfig->GetConfig(CC_FIRSTCONFIG, &strCAConfig);
if (FAILED(hr))
{
printf("Failed GetConfig [%x]\n", hr);
goto error;
}
hr = pCertAdmin->IsValidCertificate(strCAConfig, bstrSerial, &nDisp);
if (FAILED(hr))
{
printf("Failed IsValidCertificate [%x]\n", hr);
goto error;
}
if(nDisp != CA_DISP_VALID)
{
printf("givin certificate is not valid\n");
goto error;
}
// Revoke the certificate.
// pCertAdmin is a previously instantiated ICertAdmin object.
hr = pCertAdmin->RevokeCertificate( strCAConfig,
bstrSerial,
0,
0);
if (FAILED(hr))
{
/*_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();*/
//printf("Failed RevokeCertificate. [%x] [%s]\n", hr, ConvertWCSToMBS(errMsg, sizeof(errMsg)).c_str());
printf("Failed RevokeCertificate. [%x] \n", hr);
goto error;
}
else
printf("Certificate %ws revoked.\n", bstrSerial );
// Done processing.
error:
// Free resources.
if (bstrSerial)
SysFreeString( bstrSerial );
if(strCAConfig)
SysFreeString( strCAConfig );
if(pCertAdmin != NULL) { pCertAdmin->Release(); }
if(pCertConfig != NULL) { pCertConfig->Release(); }
return SUCCEEDED(hr);
}
Once you have got the issued certificate into your cert_base64 string, convert this to a byte array then create a new X509Certificate2 object from the byte array. You can then access the serial number from the X509Certificate2.SerialNumber property. In C# this would be:
X509Certificate2 x509cert = new X509Certificate2(getBytes(cert_base64));
string serialNumber = x509cert.SerialNumber;
private byte[] getBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
The code is in my OPC Client, and I want to activate a DCOM OPC Server. My purpose is to activate the OPC Server in session 1, but it works out still in session 0, i mean the OPC Server process is still run in session 0. Because the OPC Server depends on some other process in session 1, so it can't works in session 0. Can anybody helps me? It troubles my for days.
IBindCtx* pBindCtx;
HRESULT hr = CreateBindCtx(NULL, &pBindCtx);
BIND_OPTS2 stBindOpt;
ZeroMemory(&stBindOpt,sizeof(BIND_OPTS2));
stBindOpt.cbStruct = sizeof(BIND_OPTS2);
hr = pBindCtx->GetBindOptions(&stBindOpt);
stBindOpt.dwClassContext = CLSCTX_REMOTE_SERVER;
stBindOpt.grfFlags = BIND_JUSTTESTEXISTENCE;
stBindOpt.pServerInfo = &tCoServerInfo;
hr = pBindCtx->SetBindOptions(&stBindOpt);
if (FAILED(hr)) exit(0); // Handle errors here.
WCHAR wszCLSID[64];
StringFromGUID2(clsid, wszCLSID, 64);
CString strCLSID = wszCLSID;
strCLSID.Replace(_T("{"), _T(""));
strCLSID.Replace(_T("}"), _T(""));
CString strMoniker;
strMoniker.Format(_T("Session:1!clsid:%s"), strCLSID);
CLogger::Instance().WriteLog(_T("Moniker String:") + strMoniker);
nSize = strMoniker.GetLength() * sizeof(WCHAR);
LPWSTR wstrMoniker = new WCHAR[nSize];
// Copy the machine name string into the server info structure:
#ifdef _UNICODE
lstrcpyn(wstrMoniker, strMoniker, nSize);
#else
mbstowcs(wstrMoniker, strMoniker, nSize);
#endif//_UNICODE
ULONG ulParsed;
IMoniker* pMoniker;
hr = MkParseDisplayNameEx(pBindCtx,
wstrMoniker,
&ulParsed,
&pMoniker
);
if (SUCCEEDED(hr))
{
IUnknown* pSessionTestFactory;
hr = pMoniker->BindToObject(pBindCtx,
NULL,
IID_IUnknown,
(void**)&pSessionTestFactory
);
if (SUCCEEDED(hr))
{
pMoniker->AddRef();
}
pSessionTestFactory->Release();
}
pMoniker->Release();
delete [] wstrMoniker;
I am using Outlook automation to find items in the Calendar. For that I use IsSearchSynchronous() method to see if I have to wait for the AdvancedSearchComplete event. BTW, is it ever synchronous???
Anyway, if I have Outlook running, I have no problems with this call. But if it doesn't run - the call fails with
HRESULT: 0x80020009 Exception occurred
The EXCEPINFO contains:
Source: "Microsoft Outlook"
Description: "The operation failed."
scode: 0x80004005
Any suggestions?
Here is my test case:
#include <atlstr.h>
int _tmain()
{
IDispatch* pApp;
HRESULT hr;
CoInitialize(NULL);
CLSID clsid;
hr = CLSIDFromProgID(L"Outlook.Application", &clsid);
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&pApp);
if(SUCCEEDED(hr))
{
// Get DISPID for "IsSearchSynchronous"
OLECHAR Name[] = {L"IsSearchSynchronous"};
LPOLESTR lp = Name;
DISPID dispID;
hr = pApp->GetIDsOfNames(IID_NULL, &lp, 1, LOCALE_USER_DEFAULT, &dispID);
if(SUCCEEDED(hr))
{
// The path name of the folders that the search will search through.
VARIANT path;
path.vt = VT_BSTR;
path.bstrVal = SysAllocString(L"'Calendar'");
// Build DISPPARAMS
DISPPARAMS dp = { NULL, NULL, 0, 0 };
dp.cArgs = 1;
dp.rgvarg = &path;
// get IsSearchSynchronous
VARIANT result;
VariantInit(&result);
EXCEPINFO ei = {0};
hr = pApp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, &result, &ei, NULL);
VARIANT_BOOL vbIsSearchSynchronous = result.boolVal;
}
}
}
CoUninitialize();
return 0;
}
In case anybody else is interested, this is resolved with a help from Microsoft.
The “scope” parameter to a IsSearchSynchronous() call should be a complete path to the calendar folder, like:
"\\Mailbox - <user_name>\\Calendar"
Can anyone Please tell me how to get Model name of Windows Machine.
I am new to Windows VC++.
For Example i have an IBM ThinkCenter M50 running on Windows. Here the Model name is "Think Center M50". I want to get this from the System using some API.
Thanks in Advance,
Shashi Kiran G M
Alternatively, you could use the registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SystemInformation
also: HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\BIOS (Win7 or later only)
The SystemManufacturer and SystemProductName entries should do it. Saves using WMI, which i try to avoid at all costs for performance reasons.
As Ben suggests, you'll need to use WMI for this.
The class you're looking for is Win32_ComputerSystem, which contains a read-only Model property of type string that returns the product name that a manufacturer gives to a computer.
I'll leave writing the C++ code to make this WMI call as an exercise for the reader.
Do note Ben's caveat as well: not all manufacturers publish this information in the BIOS. It's very likely that IBM does, so your test case should work out fine, but this is not a universal assumption that you are justified in making. Applications should not rely on this property containing a particular value.
With the help of the Microsoft example code, I was able to create this method.
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
std::pair<CString,CString> getComputerManufacturerAndModel() {
// Obtain the initial locator to Windows Management on a particular host computer.
IWbemLocator *locator = nullptr;
IWbemServices *services = nullptr;
auto hResult = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&locator);
auto hasFailed = [&hResult]() {
if (FAILED(hResult)) {
auto error = _com_error(hResult);
TRACE(error.ErrorMessage());
TRACE(error.Description().Detach());
return true;
}
return false;
};
auto getValue = [&hResult, &hasFailed](IWbemClassObject *classObject, LPCWSTR property) {
CString propertyValueText = "Not set";
VARIANT propertyValue;
hResult = classObject->Get(property, 0, &propertyValue, 0, 0);
if (!hasFailed()) {
if ((propertyValue.vt == VT_NULL) || (propertyValue.vt == VT_EMPTY)) {
} else if (propertyValue.vt & VT_ARRAY) {
propertyValueText = "Unknown"; //Array types not supported
} else {
propertyValueText = propertyValue.bstrVal;
}
}
VariantClear(&propertyValue);
return propertyValueText;
};
CString manufacturer = "Not set";
CString model = "Not set";
if (!hasFailed()) {
// Connect to the root\cimv2 namespace with the current user and obtain pointer pSvc to make IWbemServices calls.
hResult = locator->ConnectServer(L"ROOT\\CIMV2", nullptr, nullptr, 0, NULL, 0, 0, &services);
if (!hasFailed()) {
// Set the IWbemServices proxy so that impersonation of the user (client) occurs.
hResult = CoSetProxyBlanket(services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
if (!hasFailed()) {
IEnumWbemClassObject* classObjectEnumerator = nullptr;
hResult = services->ExecQuery(L"WQL", L"SELECT * FROM Win32_ComputerSystem", WBEM_FLAG_FORWARD_ONLY |
WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &classObjectEnumerator);
if (!hasFailed()) {
IWbemClassObject *classObject;
ULONG uReturn = 0;
hResult = classObjectEnumerator->Next(WBEM_INFINITE, 1, &classObject, &uReturn);
if (uReturn != 0) {
manufacturer = getValue(classObject, (LPCWSTR)L"Manufacturer");
model = getValue(classObject, (LPCWSTR)L"Model");
}
classObject->Release();
}
classObjectEnumerator->Release();
}
}
}
if (locator) {
locator->Release();
}
if (services) {
services->Release();
}
CoUninitialize();
return { manufacturer, model };
}