event notifications not received as described - c++

Problem:
Event notifications (From COM object - Server) are not received as listed in the Sink (class) implementation.
One event notification is received (Event_one), however, others are not received accordingly
If order is changed - in IDispatch::Invoke, that is:
if Event_one is swapped to Event_two then Event_two notification received but Event_one and others neglected accordingly
Question:
Better way to implement, IDispatch::Invoke or QI?
Using the wrong logic or approach?
Note:
No MFC
No ATL
Pure C++
using message loop: GetMessage()
STA model ( Coinitialize() )
Call to IDispatch::Advise successful (HRESULT from call S_OK)
After above, COM object method calls as normal (with interface pointer)
Single call to Advise
Type library generated from MIDL compiler
For instance (example):
Illustration of IDispatch::Invoke - taken from Sink Class:
HRESULT STDMETHODCALLTYPE Invoke(
{
//omitted parameters
// The riid parameter is always supposed to be IID_NULL
if (riid != IID_NULL)
return DISP_E_UNKNOWNINTERFACE;
if (pDispParams) //DISPID dispIdMember
{
switch (dispIdMember) {
case 1:
return Event_one();
case 2:
return Event_two();
case 3:
return Event_three();
default:
return E_NOTIMPL;
}
}
return E_NOTIMPL;
}
Illustration of QueryInterface:
STDMETHOD (QueryInterface)(
//omitted parameters
{
if (iid == IID_IUnknown || iid == __uuidof(IEvents))
{
*ppvObject = (IEvents *)this;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
m_dwRefCount++;
return S_OK;
};

Since you are receiving the notification for first method of the sink interface, I suspect, events are not sent on other methods from Server. If you have code of the server, just check the connection point class which throws the notifications.
You can also put a breakpoint in Invoke method of client application to check what are all the events it is receiving.

SOLVED:
After reviewing the corresponding IDL FILE (generated by the MIDL compiler), it was evident that each method contained in the IEvent interface, has a unique ID. For instance, Event_one has an ID of 2. For example:
methods:
[id(0x00000002)]
HRESULT Event_one();
Therefore, making a change as followings - in the IDispatch::invoke implementation (illustrated in the above question):
//omitted
if (pDispParams) //DISPID dispIdMember
{
switch (dispIdMember) {
case 2:
return Event_one();
//omitted
Now when invoked accordingly, the desired/correct method is now executed.

Related

How to implement OOBE complete notification in c++?

I want to do a win32 implementation of RegisterWaitUntilOOBECompleted API for my app.
The goal is to detect OOBE complete and perform specific operations.
However, I don't quite understand how to implement it in c++ code.
I spent the past 6 hours looking for sample implementation but to no luck.
Can anyone explain how to do it?
Registers a callback to be called once OOBE (Windows Welcome) has been
completed.
Syntax C++
BOOL RegisterWaitUntilOOBECompleted( OOBE_COMPLETED_CALLBACK
OOBECompletedCallback, PVOID CallbackContext,
PVOID *WaitHandle );
Parameters
OOBECompletedCallback
Pointer to an application-defined callback function that will be
called upon completion of OOBE. For more information, see
OOBE_COMPLETED_CALLBACK.
CallbackContext
Pointer to the callback context. This value will be passed to the
function specified by OOBECompletedCallback. This value can be nulll.
WaitHandle
Pointer to a variable that will receive the handle to the wait
callback registration.
For anyone in the future who might be looking for sample implementation of this API, here's how I did it. This sample code is not intended to compile though.
Header file
#include "Oobenotification.h"
class MainClass
{
// put constructor here
// destructor
~MainClass();
// OOBE notification
OOBE_COMPLETED_CALLBACK OOBECompletedCallback;
PVOID m_OOBEHandle = NULL;
// receive notification one OOBE complete
void OOBERegisterNotification();
static void CALLBACK NotifyOOBEComplete(PVOID CallbackContext);
public:
Init();
};
CPP file
#include "header.h"
void MainClass::~MainClass()
{
if (m_OOBEHandle != NULL)
UnregisterWaitUntilOOBECompleted(m_OOBEHandle);
}
void MainClass::Init()
{
// register to receive oobe complete notification
OOBERegisterNotification();
}
void MainClass::OOBERegisterNotification()
{
OOBECompletedCallback = &NotifyOOBEComplete;
BOOL bRes = ::RegisterWaitUntilOOBECompleted(OOBECompletedCallback, NULL, &m_OOBEHandle);
if (!bRes)
{
// handle failed registration here
}
}
void CALLBACK MainClass::NotifyOOBEComplete(PVOID Context)
{// async
UNREFERENCED_PARAMETER(Context);
// what you want to do after OOBE
}

How to deny a called process to write to the inherited console window

I'm writing a program which can call multiple processes and keep track of them. Since this is a school project, I only need to call compiled code (.exe) that has simple tasks (array sorts, list sorts etc). The problem is that my PARENT PROCESS has an ascii console interface built with moveCursor(x,y) and if the CHILD PROCESS has an std::cout or printf() it writes over my PARENT PROCESS interface.
QUESTION: Whithout modifying the CHILD PROCESSES code to simply don't have screen prints how can i deny the inheritance of the PARENT PROCESS console window and block the CHILD PROCESSES to create a new console window?
I'm using CreateProcess() to start the processes.
I'm looking for a WINDOWS solution.
Here is my Process class which i use to manage my processes.
class Process
{
private:
STARTUPINFO startInfo;
PROCESS_INFORMATION processInfo;
CHAR pathToExe[EXTENDED_MAX_PATH];
DWORD returnedValue;
public:
/** I don't know how to pass a LPCSTR parameter to the constructor so i simply use
another function to construct the class */
/** I also don't want a global string and to simply modify it before i declare my object */
bool Create(LPCSTR pathToFile)
{
ZeroMemory(&startInfo,sizeof(startInfo));
ZeroMemory(&processInfo,sizeof(processInfo));
ZeroMemory(&pathToExe,sizeof(pathToExe));
ZeroMemory(&returnedValue,sizeof(returnedValue));
strcpy(pathToExe,pathToFile);
bool hasProcessStarted = CreateProcess(pathToFile,NULL,NULL,NULL,FALSE,0,NULL,NULL,&startInfo,&processInfo);
return hasProcessStarted;
}
bool IsRunning()
{
if (GetExitCodeProcess(processInfo.hProcess,&processInfo.dwProcessId))
if (processInfo.dwProcessId == STILL_ACTIVE) return true;
return false;
}
/** Kind of a destructor. I just made another function because its easier to manage all the data*/
/** Also all the Process Class Objects are dynamically allocated so i just simply delete them after Kill() returns true*/
bool Kill(bool skipIfRunning)
{
if (skipIfRunning == true && IsRunning()) return false;
if (TerminateProcess(processInfo.hProcess,0))
{
ZeroMemory(&startInfo,sizeof(startInfo));
ZeroMemory(&processInfo,sizeof(processInfo));
ZeroMemory(&pathToExe,sizeof(pathToExe));
ZeroMemory(&returnedValue,sizeof(returnedValue));
return true;
}
return false;
}
DWORD GetProcessReturnedValue()
{
return processInfo.dwProcessId;
}
};
The second parameter of the CreateProcess is the "command line".
Use it (instead of NULL) and redirect otputs to "null"
mycommandline = fullFilePath + " 1>nul 2>nul"
CreateProcess(pathToFile, mycommandline , ...)

Default HRESULT hResult = E_NOTIMPL?

I am working on a win7 based system using silverlight for embedded for UI graphics and C++ for firmware. I have noticed that in many of the existing functions (written before i was brought onto the project), there is some code that i am not quite sure what it is doing.
HRESULT AddAlarm::AlarmType_SelectionChanged (IXRDependencyObject* pSender, XRSelectionChangedEventArgs* pArgs)
{
HRESULT hResult = E_NOTIMPL;
if((NULL == pSender)||(NULL==pArgs))
{
hResult = E_INVALIDARG;
}
//Code to set visibility of UI elements
if(index ==0) //index is the threshold type index from the combobox. Can be 0-3.
{
m_pAlarmLowThreshold->SetVisibility(XRVisibility_Collapsed);
}
//Code repeats for other threshold types and visibility states.
return hResult;
}
The if statement is pretty straightforward and the function returns hResult, but i dont understand the declaration HRESULT hResult = E_NOTIMPL;. It is declaring a variable of type HRESULT and assigning it a default HRESULT value of E_NOTIMPL, but since the function doesnt modify this value outside of the if statement, doesnt this mean that it remains as E_NOTIMPL, basically telling the system that it (something) is not implemented or is wrong?
I know that when this king of method is automatically generated trought the VS interface. The inside code is always something like
return E_NOTIMPL;
I think what your predecessors tried to do is beeing clean in there way to develop the method by assuring them self that all case are processed by starting with an E_NOTIMPL that should be changed during method's processing.
This kind of method should return s_OK when it works fine. Here is a list of possible codes :
http://msdn.microsoft.com/en-us/library/windows/desktop/aa378137%28v=vs.85%29.aspx
If there is no assigning of an S_OK it means indeed that the function is not fully implemented thus an E_NOTIMPL seems correct (or not :) )

API Hook on a COM object function?

Greetings StackOverflowians,
As discovered here, Windows 7 features a bug in which the DISPID_BEFORENAVIGATE2 event does not fire for Windows Explorer instances. This event allows shell extensions to be notified when a navigation is about to take place, and (most importantly for me) have the opportunity to cancel the navigation. I've been looking for a workaround for quite some time, and I think I found one. But, I'd like to get some opinions on how safe it is.
I've been playing with API hooking a lot lately, and I'm already using it to hook a few functions for my extension. I noticed that there is a function in IShellBrowser that controls navigation. At first I thought you couldn't hook something like that, but upon reading about the layout of a COM object I realized it should be possible by just grabbing the right function pointer out of the vtable of any active instance. Sure enough, it works like a dream. After the hook is set, all navigations in all Explorer windows run right through my detour function, and I can decide whether to reject them based on their target pidl.
So my question is, is there any reason I should NOT do this? I've never heard of API hooking used to hook COM object functions. Are there circumstances it which it wouldn't work? Is it dangerous? (Any more than regular API hooking, at least)
The relevant code follows. I'm using MinHook, a minimalistic hooking library that uses the tried-and-true method of trampoline functions.
typedef HRESULT (WINAPI *BROWSEOBJECT)(IShellBrowser*, PCUIDLIST_RELATIVE, UINT);
HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags);
BROWSEOBJECT fpBrowseObject = NULL;
BROWSEOBJECT ShellBrowser_BrowseObject = NULL;
bool Initialize() {
if(MH_Initialize() != MH_OK) {
return false;
}
// Get a reference to an existing IShellBrowser. Any instance will do.
// ShellBrowser enum code taken from The Old New Thing
IShellWindows *psw;
BOOL fFound = FALSE;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw))) {
VARIANT v;
V_VT(&v) = VT_I4;
IDispatch *pdisp;
for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) {
IWebBrowserApp *pwba;
if (SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
IServiceProvider *psp;
if (SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
IShellBrowser *psb;
if (SUCCEEDED(psp->QueryService(SID_STopLevelBrowser,IID_IShellBrowser, (void**)&psb))) {
fFound = true;
// Grab the 11th entry in the VTable, which is BrowseObject
void** vtable = (*(void***)(psb));
ShellBrowser_BrowseObject = (BROWSEOBJECT)(vtable[11]);
psb->Release();
}
psp->Release();
}
pwba->Release();
}
pdisp->Release();
}
psw->Release();
}
if(fFound) {
if(MH_CreateHook(ShellBrowser_BrowseObject, &DetourBrowseObject, reinterpret_cast<void**>(&fpBrowseObject)) != MH_OK) {
return false;
}
if(MH_EnableHook(ShellBrowser_BrowseObject) != MH_OK) {
return false;
}
}
return true;
}
HRESULT WINAPI DetourBrowseObject(IShellBrowser* _this, PCUIDLIST_RELATIVE pidl, UINT wFlags) {
if(NavigateIsOkay(pidl, wFlags)) {
return fpBrowseObject(_this, pidl, wFlags);
}
else {
return S_FALSE;
}
}
I've never heard of API hooking used
to hook COM object functions.
Member functions of COM Objects are not really that different and can actually be hooked just fine if you stick to the usual guidelines for hooking. A few years ago, I had to hook COM components of a proprietary CRM solution to connect it to a database server. The application worked fine and has been running quite stable for several years.

Comparing objects with IDispatch to get main frame only (BHO)

I don't know if anyone familiar with BHO (Browser Helper Object), but an expert in c++ can help me too.
In my BHO I want to run the OnDocumentComplete() function only on the main frame - the first container and not all the Iframes inside the current page. (an alternative is to put some code only when this is the main frame).
I can't find how to track when is it the main frame that being populated.
After searching in google I found out that each frame has "IDispatch* pDisp", and I have to compare it with a pointer to the first one.
This is the main function:
STDMETHODIMP Browsarity::SetSite(IUnknown* pUnkSite)
{
if (pUnkSite != NULL)
{
// Cache the pointer to IWebBrowser2.
HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
if (SUCCEEDED(hr))
{
// Register to sink events from DWebBrowserEvents2.
hr = DispEventAdvise(m_spWebBrowser);
if (SUCCEEDED(hr))
{
m_fAdvised = TRUE;
}
}
}
else
{
// Unregister event sink.
if (m_fAdvised)
{
DispEventUnadvise(m_spWebBrowser);
m_fAdvised = FALSE;
}
// Release cached pointers and other resources here.
m_spWebBrowser.Release();
}
// Call base class implementation.
return IObjectWithSiteImpl<Browsarity>::SetSite(pUnkSite);
}
This is where I want to be aware whether its the main window(frame) or not:
void STDMETHODCALLTYPE Browsarity::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
// as you can see, this function get the IDispatch *pDisp which is unique to every frame.
//some code
}
I asked this question on Microsoft forum and I got an answer without explaining how to actually implement that: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/7c433bfa-30d7-42db-980a-70e62640184c
What jeffdav suggested is, to test wether the pDisp supports IWebBrowser2 via QueryInterface(), and if so, to check wether it is the same object as the one you stored in SetSite().
The QueryInterface() rules only require that a QI for IUnknown always results in the same pointer value, so you have to additionally QI to IUnknown and compare the resulting pointers.
This would lead to something like this in OnDocumentComplete():
IWebBrowser2* pBrowser = 0;
IUnknown *pUnk1=0, *pUnk2=0;
if( SUCCEEDED(pDisp ->QueryInterface(IID_IWebBrowser2, (void**)&pBrowser))
&& SUCCEEDED(pDisp ->QueryInterface(IID_IUnknown, (void**)&pUnk1))
&& SUCCEEDED(m_spBrowser->QueryInterface(IID_IUnknown, (void**)&pUnk2))
&& (pUnk1 == pUnk2))
{
// ... top-level
}
... or if you are using ATL (as m_spWebBrowser suggests):
CComQIPtr<IWebBrowser2> spBrowser(pDisp);
if(spBrowser && spBrowser.IsEqualObject(m_spWebBrowser)) {
// ...
}
Notice that I did not test this, I'm only rewriting what the guy on msdn said.
In ::SetSite you get an IUnknown pointer. Call IUnknown::QueryInterface on it (just like you're already doing), but instead use IID_IDISPATCH. Save this pointer somewhere, this pointer is the top level frame.
In ::OnDocumentComplete you're getting a IDispatch pointer, compare this one to the previous saved ptr and voĆ­la, if there is a match you're in the top level.