ROT registration does not work with adobe 11 installed - c++

I have code that we've been using for years with PDFs, HTML docs, and XBRL docs. The code is called from either a BHO in IE, or an Adobe plugin in Reader. It registers a moniker in the ROT, and creates a signalling event.
We've been trying to upgrade from Adobe 9 to Adobe 11, and the debugging the code, it simply fails to register the moniker in the ROT. It works if called from an Adobe 9 plugin, and if called from the BHO. But simply upgrading to Adobe 11 is enough to make it start silently failing.
The code in question is below:
void CLocatorRegistration::Register( ISourceLocator* pLocator, long nKeyFile )
{
HRESULT hr;
CComPtr<IRunningObjectTable> pROT;
CComPtr<IMoniker> pmk;
CComBSTR bstrName;
// access the ROT
pROT = GetROT();
// create the moniker
pmk = CreateMoniker( nKeyFile );
// put this object in the ROT.
_ASSERTE( !m_bRegistered );
->>hr = pROT->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE, pLocator, pmk, &m_dwROTCookie );
if FAILED(hr)
throw hr;
m_bRegistered = true;
// create the event and signal it, to support notification to any callers that this object
// is now available to connect to
CreateEventName( nKeyFile, bstrName );
m_hEvent.Attach( ::CreateEvent( NULL, TRUE, FALSE, bstrName ));
::SetEvent( m_hEvent );
}
The highlighted line is the ROT registration, and the return is S_OK. Does anyone have any idea why the method would succeed, but the entry not be placed into the ROT?

The problem that I found in researching this was the fact that Adobe 11 includes a new sandboxed protected mode setting. When developing a plugin, it no longer by default has access to the OS.
For our purposes it was quite simple just to disable this setting, as this is for an internal application. There are a lot of other ways to accomplish this, but we didn't look into them because of time constraints.

Related

WebView2 proxy C++

I found this thread on GitHub, but seems that the code is not C++:
WebView2 _webView2 = new WebView2();
CoreWebView2EnvironmentOptions options = new CoreWebView2EnvironmentOptions();
// Set a proxy pac for the browser
// options.AdditionalBrowserArguments = "--proxy-pac-url=http://myproxy.com/my.pac";
// Set the proxy for the browser
options.AdditionalBrowserArguments = "--proxy-server=\"foopy:99\"";
// Create the environment manually
CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, null, options);
await _webView2 .EnsureCoreWebView2Async(env);
So the only what am I asking for is to provide the solution for setting up a proxy for WebView2 via C++.
I have ICoreWebView2 interface, but it doesn’t have EnsureCoreWebView2Async method. In another hand, I have CoreWebView2EnvironmentOptions class.
auto opt = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
opt->put_AdditionalBrowserArguments(L"--proxy-server=\"SERVER\"");
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, opt.Get(), Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hwnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
...
}).Get());
Instead of SERVER put ip address or something else.
I tested, it works, but seems there is a bug (or feature): you can’t create two or more webviews with different run-arguments.
To those looking to specify webview environment options and cannot find CoreWebView2EnvironmentOptions in C++ similar to what is available in .Net. Visit documentation page for ICoreWebView2EnvironmentOptions and you should find this line:
A default implementation is provided in WebView2EnvironmentOptions.h
Include WebView2EnvironmentOptions.h and create CoreWebView2EnvironmentOptions as below
#include <WebView2EnvironmentOptions.h>
auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
// Use options however you want. I simply added an argument to autoplay videos.
options->put_AdditionalBrowserArguments(L"--autoplay-policy=no-user-gesture-required");
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
subFolder, m_userDataFolder.c_str(), options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
this, &AppWindow::OnCreateEnvironmentCompleted)
.Get());

Unable to Retrieve IMFAudioPolicy from Media Session

I have developed Win32 app based heavily on the MF_ProtectedPlayback sample here. I'm using 4 cplayer objects at a time. It works for what I need it to do.
However, I am trying to group the sessions, so that they are controlled by one volume control in control panel, as described in docs here.
My problem is that I cannot get the IMFAudioPolicy (MR_AUDIO_POLICY_SERVICE) from the session. As in the sample, I'm using the MFCreateAudioRendererActivate() method to create the renderers. Again, this all works fine. I have no problem getting other interfaces back from the session, like IMFSimpleAudioVolume.
I get the following errors:
-onecore\com\combase\dcomrem\call.cxx(4907)\combase.dll!75EB0755: (caller: 75E931D8) ReturnHr(3) tid(7e60) 80040155 Interface not registered
-Exception thrown at 0x773DA892 (KernelBase.dll) in MyApp.exe: 0x80040155: Interface not registered.
Relevant code:
HRESULT CPlayer::OnTopologyReady(IMFMediaEvent* pEvent)
{
\\ works fine
MFGetService(
m_pSession,
MR_VIDEO_RENDER_SERVICE,
__uuidof(IMFVideoDisplayControl),
(void**)&m_pVideoDisplay
);
\\ works fine
MFGetService(
m_pSession,
MR_POLICY_VOLUME_SERVICE,
__uuidof(IMFSimpleAudioVolume),
(void**)&m_pSimpleVolume
);
// winrt errors, returns null
MFGetService(
m_pSession,
MR_AUDIO_POLICY_SERVICE,
__uuidof(IMFAudioPolicy),
(void**)&m_pAudioPolicy
);
HRESULT hr = StartPlayback();
return S_OK;
}
What am I missing? Any ideas why this interface is not available? Thanks...
-jerry
edit: so it appears that what I want to do may not be possible. This problem is related to the protected processes created in PMP. Still investigating...

Forward credentials from app to credential provider

I've started to investigate how credential providers work, but due to poor documentation I got stuck in couple of places.
I have console application(sort of like ssh server) when I connect remotly to this application and authenticate(none is logged on), I want it to be able to forward those credentials to credential provider and I want CP to login user(create session).
I've also noticed that In documentation it says that SetSerialization method always gets called after SetusageScenario. But I've added logs and SetSerialization never gets called after SetusageScenario.
As I know SetSerialization is called when credential is provided by application. I can't understand what does it mean to provide credential through application? It seems like this is what I need, to forward credentials from application to credential provider, but How can I do that? Are there some functions that I could call from credential provider dll to provoke login?
Is there any way I can achieve this? I've read that when remote login is done, UpdateRemoteCredential is called, But As I understand(correct me if I'm wrong) in remote login it means RDP but my application is simple, it just listens to some port and gets username and password and then uses Logonuser function.
A program named MxLogon2 implements this scheme. A remote server with MxLogon2 installed can authenticate a USB key(But I want username/password) connected to the client side in a remote desktop session.
Any suggestion that would direct me to right way would be greatly appriciated.
P.S
I'm using pGina as my credential provider.
I wouldn't mind too much of SetSerialization in your case. This is used for pre-initializing tile.
One example would be, with RDP connection, you can store certificates of credentials on your system. This function is used to pre-inquire tiles with those credentials (not the only solution though).
Make it return E_NOTIMPL in your case.
The main purpose of the provider is to initialize Credentials and tiles :
Credentials initialization
is done through SetUsageScenario function (automatically called after Provider construction).
In there, you can customize the behavior depending on scenario you are in. Most basic one being CPUS_LOGON.
It shall look like this (this is only a preview)
HRESULT Provider::SetUsageScenario(
__in CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
__in DWORD dwFlags
)
{
HRESULT hr;
switch(cpus)
{
case CPUS_UNLOCK_WORKSTATION:
case CPUS_LOGON:
hr = this->_InitCredential();
break;
default:
hr = E_INVALIDARG;
break;
}
return hr;
}
Tiles initialization
begins in GetCredentialCount function. It allows you to define how many tiles you gonna show (pdwCount out parameter), as well as the one to be used as the default tile (pdwDefault).
Auto-Logon is also handle in here (through pbAutoLogonWithDefault).
Tiles Enumeration is then beginning in GetCredentialAt function.
Passing credentials for authentication is done in the credential you're using through the GetSerialization function.
Examples of implementation can be found here.
I hardly insist on example as it easily divert depending on what you are trying to achieve. This is very flexible and you'd better understand the purpose of any function / parameter to fit your goals.
EDIT - cf comments :
#define IDCredential 0x1
Credential::Credential(Provider* parent)
{
//Do ssh connection or whatever
if(success)
{
parent->login = retrievedLogin;
parent->pwd = retrievedPwd;
parent->CredentialUsed = IDCredential;
parent->autoLogin = true;
parent->ProviderEvents->CredentialsChanged(AdviseContext);
}
}
HRESULT Provider::GetCredentialCount(
__out DWORD* pdwCount,
__out_range(<,*pdwCount) DWORD* pdwDefault,
__out BOOL* pbAutoLogonWithDefault
)
{
if(this->autoLogin && this->CredentialUsed)
{
*pbAutoLogonWithDefault = true; // --> Instant call to GetSerialization
*pdwDefault = this->CredentialUsed; //index of the tile
}
else
{
*pbAutoLogonWithDefault = false;
*pdwDefault = IDCredential;
}
return S_OK;
}

IServiceProvider::QueryService fails with error -2147024809 on Windows server 2008 R2 having IE11

Acquiring the IAccessible pointer to an element within the page or the accessible window of the document for Window class Internet Explorer_Server is successfully using the code (where hwnd is the handle of Internet_Explorer_server) AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**)&pAcc)
Getting an IServiceProvider interface pointer for the accessible object obtained from Step 1 is also successfully using the code HRESULT hr;
hr = pAcc->QueryInterface(IID_IServiceProvider, (void **)&pSP).
However when tried to use the QueryService call on the obtained IServiceProvider using the code HRESULT hr = pServiceProvider->QueryService(IID_IHTMLWindow2, IID_IHTMLWindow2, (void**)&pWindow)it fails with a return -2147024809, which is 0x80070057. Not sure as to why this is happening, just wondering if there are any specific setting on the server machine (Windows Server 2008 R2) which is preventing this call from being successfully. Also, the above step which I have described is successfully in Windows 7 environment.To Note : Version of Internet Explorer installed is 10

Calling remote COM component from MFC client?

I have a COM component that was originally written in Visual Studio 6. It is in a windows service which I have running on one of my development machines. I have written a quick MFC test app to call it and this works fine when run from this machine, the code looks like
COSERVERINFO si;
MULTI_QI qi;
COAUTHINFO cai = { RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0,RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE,0, EOAC_NONE };
si.dwReserved1 = 0;
si.pwszName =L"{machine name}";
si.pAuthInfo = &cai;
si.dwReserved2 = 0;
qi.pIID = &IID_IMyComponent;
qi.pItf = NULL;
qi.hr = 1;
HRESULT hr = CoCreateInstanceEx(CLSID_MyComponent,NULL,CLSCTX_REMOTE_SERVER ,&si,1,&qi);
However, when I move the MFC test app to my other development machine and try and call the component on the other machine it fails. The hresult returned from CoCreateInstanceEx is -2147024891
I have already created the proxy stub DLL and registered it on both machines. Am I missing something else?
UPDATE:
I now updated the COUTHINFO structure to the below and it works.
COAUTHINFO cai = { RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,0, EOAC_NONE };
The ERROR_ACCESS_DENIED is most likely due to the wrong parameters supplied with COAUTHINFO. You set Authentication, Authorization levels to NONE, which is not enough to get permissions to connect with remote machine. Try to set these values: RPC_C_AUTHN_DEFAULT (have COM negotiate the best authentication service), RPC_C_AUTHZ_NONE, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE. Also see the MSDN source - COAUTHINFO structure
An HRESULT of -2147024891 (or 0x80070005 when converted to hex) is ERROR_ACCESS_DENIED. So it's a permission error when trying to connect to the remote machine.
The error means E_ACCESS_DENIED. Make sure the current user has the rights to access the component. Run dcomcnfg (or "Component Services") on the server box, under "DCOM Config" find the right component, under "Security" change the permissions to allow both activation and access for the calling user.
Or make sure the calling user is an admin on the server box.