ATL Service - Need to establish sink for a connection point of ActiveX dll 
Author Message
 ATL Service - Need to establish sink for a connection point of ActiveX dll

Hi,

I have an ActiveX dll with a connection point, and i need to use it in the
ATL service.
I tried to create and MFC based class ( class CNotify : public CCmdTarget )
with the appropriate definitions for the sink event:

BEGIN_DISPATCH_MAP( CNotify, CCmdTarget)
 DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY,
VTS_R8)
END_DISPATCH_MAP( )

BEGIN_INTERFACE_MAP( CNotify, CCmdTarget)
 INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch)
END_INTERFACE_MAP()

(this class is in test use in MFC application and the sink event is working)

at the constructor of this class i execute the AfxConnectionAdvise method:

  BOOL Ret = ::AfxConnectionAdvise(
     m_pRepTimer,
     DIID___ciTimer,
     GetIDispatch(FALSE), //get the IDispatch assocaiated with
CServiceManagerDlg...
     FALSE, //donod addref
     &dwCookie );//cookie to break connection later...

so in MFC application the sink is working and in ATL service it failed and i
don't know why.

I tried another test, the same class using ATL instead of MFC :
class CNotifyEvents :
  public IDispatchImpl<__ciTimer, &DIID___ciTimer,
   &CLSID_ciTimer>,
  public CComObjectRoot

and instead of AfxConnectionAdvise i used :

   HRESULT hr=AtlAdvise(m_pRepTimer,
    GetUnknown(),
    DIID___ciTimer,
    &dwCookie);

I think that my Major problem is at the second parameter GetUnknown() ( or
in the first case, the third parameter :  GetIDispatch(FALSE) )  that failes
in ATL service, can somebody help me to know how can i establish sink event
in NON-WINDOWS environment ?
Is there any special solution for ATL service?

Thank you,
Ofir



Fri, 27 Aug 2004 17:45:17 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi,

see inline:


Quote:
> Hi,

> I have an ActiveX dll with a connection point, and i need to use it in the
> ATL service.
> I tried to create and mfc based class ( class CNotify : public
CCmdTarget )
> with the appropriate definitions for the sink event:

> BEGIN_DISPATCH_MAP( CNotify, CCmdTarget)
>  DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY,
> VTS_R8)
> END_DISPATCH_MAP( )

> BEGIN_INTERFACE_MAP( CNotify, CCmdTarget)
>  INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch)
> END_INTERFACE_MAP()

> (this class is in test use in MFC application and the sink event is
working)

> at the constructor of this class i execute the AfxConnectionAdvise method:

>   BOOL Ret = ::AfxConnectionAdvise(
>      m_pRepTimer,
>      DIID___ciTimer,
>      GetIDispatch(FALSE), //get the IDispatch assocaiated with
> CServiceManagerDlg...
>      FALSE, //donod addref
>      &dwCookie );//cookie to break connection later...

> so in MFC application the sink is working and in ATL service it failed and
i
> don't know why.

> I tried another test, the same class using ATL instead of MFC :
> class CNotifyEvents :
>   public IDispatchImpl<__ciTimer, &DIID___ciTimer,
>    &CLSID_ciTimer>,
>   public CComObjectRoot

> and instead of AfxConnectionAdvise i used :

>    HRESULT hr=AtlAdvise(m_pRepTimer,
>     GetUnknown(),
>     DIID___ciTimer,
>     &dwCookie);

You call AtlAdvise from within a CNotifyEvents instance method? Otherwise
there will be no GetUnknown() method to call.
What is the hr value.

Quote:
> I think that my Major problem is at the second parameter GetUnknown() ( or
> in the first case, the third parameter :  GetIDispatch(FALSE) )  that
failes
> in ATL service, can somebody help me to know how can i establish sink
event
> in NON-WINDOWS environment ?
> Is there any special solution for ATL service?

What do you mean by establish a sink event in a NON-WINDOWS environment???

Bye,
Sven



Fri, 27 Aug 2004 21:57:19 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi,


Quote:
> Hi Sven,

> You call AtlAdvise from within a CNotifyEvents instance method?

> --yes, i am doing so, why? it did work at the first test when i used
> AfxConnectionAdvise.
> --is there difference in the location of  AfxConnectionAdvise and
AtlAdvise
> ?

Just wanted to make sure that ATL's GetUnknown() is called and returns the
valid IUnknown*.

Quote:
> What is the hr value?

> -- in the service i don't know, because i don't know how to debug it on
the
> first time, before it creates the process, and it create a process for it
> -- just after the the execution of the Start of the service
> -- i know that the problem is there because when i remove the AtlAdvise it
> does not fail.

> -- the AtlAdvice failed also in the MFC application test, and i have no
idea
> why
> -- I get the message box  : "Runtime error - R6025 - pure virtual function
> call"  , with Abord/Retry/Ignore buttons, and when i press Retry i get to
> \VC98\CRT\SRC\CRTOMSG.C to the lines :

>             if (rterrnum != _RT_CRNL)
>             {
>                 if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL,
> rterrs[tblindx].rterrtxt))
>                     _CrtDbgBreak();
>             }

> So i don't know why it failes.

Have a look at the call stack to see from where the _CrtDbgReport is called.

- Show quoted text -

Quote:
> I did not find any example of service with sink event on the MSDN and i
> don't understand what is the problem
> I am attaching  a zip file of the two classes of the tests (CNotify,
> CNotifyEvent) in case that it is interesting you.
> the CNotify class is working on MFC Application but does not work on ATL
> service
> the CNotifyEvent class does not working on both.

> > What do you mean by establish a sink event in a NON-WINDOWS
environment???

> I am not sure, but as much as i understood the Advise functions expect to
> get an IUnknown pointer to a window interface that suppose to be able to
> handle/accept messages, and in the case of  the AtlService i don't think
> that i have one.
> so can you please tell me which IUnknown suppose to be the client's
IUnknown
> (in my case my class CNotifyEvents suppose to handle the sink) in case of
> ATL service ?
> Do you have any basice example of the usage of Sink in the ATL service ? I
> will be thankful for that.

COM events have nothing to do (well except if marshaling comes in the way
but that's kind of transparent if you behave well ;-) ) windows.
GetUnknown() should return the IUnknown implementation fo ATL for your
object. There is an ambiguity when casting your C++ class to IUnknown when
you implement more than one interface so GetUnknown helps in returning the
correct IUnknown*.

How do you create a CNotifyEvents instance - can I see some code?

Bye,
Sven

- Show quoted text -

Quote:

> Thank you for the help Sven,

> Ofir



> > Hi,

> > see inline:



> > > Hi,

> > > I have an ActiveX dll with a connection point, and i need to use it in
> the
> > > ATL service.
> > > I tried to create and mfc based class ( class CNotify : public
> > CCmdTarget )
> > > with the appropriate definitions for the sink event:

> > > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget)
> > >  DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY,
> > > VTS_R8)
> > > END_DISPATCH_MAP( )

> > > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget)
> > >  INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch)
> > > END_INTERFACE_MAP()

> > > (this class is in test use in MFC application and the sink event is
> > working)

> > > at the constructor of this class i execute the AfxConnectionAdvise
> method:

> > >   BOOL Ret = ::AfxConnectionAdvise(
> > >      m_pRepTimer,
> > >      DIID___ciTimer,
> > >      GetIDispatch(FALSE), //get the IDispatch assocaiated with
> > > CServiceManagerDlg...
> > >      FALSE, //donod addref
> > >      &dwCookie );//cookie to break connection later...

> > > so in MFC application the sink is working and in ATL service it failed
> and
> > i
> > > don't know why.

> > > I tried another test, the same class using ATL instead of MFC :
> > > class CNotifyEvents :
> > >   public IDispatchImpl<__ciTimer, &DIID___ciTimer,
> > >    &CLSID_ciTimer>,
> > >   public CComObjectRoot

> > > and instead of AfxConnectionAdvise i used :

> > >    HRESULT hr=AtlAdvise(m_pRepTimer,
> > >     GetUnknown(),
> > >     DIID___ciTimer,
> > >     &dwCookie);

> > You call AtlAdvise from within a CNotifyEvents instance method?
Otherwise
> > there will be no GetUnknown() method to call.
> > What is the hr value.

> > > I think that my Major problem is at the second parameter GetUnknown()
> ( or
> > > in the first case, the third parameter :  GetIDispatch(FALSE) )  that
> > failes
> > > in ATL service, can somebody help me to know how can i establish sink
> > event
> > > in NON-WINDOWS environment ?
> > > Is there any special solution for ATL service?

> > What do you mean by establish a sink event in a NON-WINDOWS
environment???

> > Bye,
> > Sven



Sat, 28 Aug 2004 00:34:41 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi,

I had a look at your attachments.

You are calling AtlAdvise from within your constructor: m_pReqTimer is still
NULL at that time.
InitiateReplication is a far better place. What's your problem with calling
AtlAdvise at that point?

GetIDispatch is a helper function from MFC's CCmdTarget to get the
corresponding IDispatch interface from an CCmdTarget derived class - it's
just not available if don't use MFC to implement your COM object. In ATL you
should use GetUnknown().

What's still missing is how do you create an instance of CNotifyEvents? It
should be:

CComObject<CNotifyEvents> *p = NULL;
HRESULT hr = p->CreateInstance(&p);
if(FAILED(hr))
{
   // ouch
   delete p;

Quote:
}

else
{
   p->InitiateReplication();

Quote:
}

Bye,
Sven


Quote:
> Hi Sven,

> You call AtlAdvise from within a CNotifyEvents instance method?

> --yes, i am doing so, why? it did work at the first test when i used
> AfxConnectionAdvise.
> --is there difference in the location of  AfxConnectionAdvise and
AtlAdvise
> ?

> What is the hr value?

> -- in the service i don't know, because i don't know how to debug it on
the
> first time, before it creates the process, and it create a process for it
> -- just after the the execution of the Start of the service
> -- i know that the problem is there because when i remove the AtlAdvise it
> does not fail.

> -- the AtlAdvice failed also in the MFC application test, and i have no
idea
> why
> -- I get the message box  : "Runtime error - R6025 - pure virtual function
> call"  , with Abord/Retry/Ignore buttons, and when i press Retry i get to
> \VC98\CRT\SRC\CRTOMSG.C to the lines :

>             if (rterrnum != _RT_CRNL)
>             {
>                 if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL,
> rterrs[tblindx].rterrtxt))
>                     _CrtDbgBreak();
>             }

> So i don't know why it failes.

> I did not find any example of service with sink event on the MSDN and i
> don't understand what is the problem
> I am attaching  a zip file of the two classes of the tests (CNotify,
> CNotifyEvent) in case that it is interesting you.
> the CNotify class is working on MFC Application but does not work on ATL
> service
> the CNotifyEvent class does not working on both.

> > What do you mean by establish a sink event in a NON-WINDOWS
environment???

> I am not sure, but as much as i understood the Advise functions expect to
> get an IUnknown pointer to a window interface that suppose to be able to
> handle/accept messages, and in the case of  the AtlService i don't think
> that i have one.
> so can you please tell me which IUnknown suppose to be the client's
IUnknown
> (in my case my class CNotifyEvents suppose to handle the sink) in case of
> ATL service ?
> Do you have any basice example of the usage of Sink in the ATL service ? I
> will be thankful for that.

> Thank you for the help Sven,

> Ofir



> > Hi,

> > see inline:



> > > Hi,

> > > I have an ActiveX dll with a connection point, and i need to use it in
> the
> > > ATL service.
> > > I tried to create and mfc based class ( class CNotify : public
> > CCmdTarget )
> > > with the appropriate definitions for the sink event:

> > > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget)
> > >  DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY,
> > > VTS_R8)
> > > END_DISPATCH_MAP( )

> > > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget)
> > >  INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch)
> > > END_INTERFACE_MAP()

> > > (this class is in test use in MFC application and the sink event is
> > working)

> > > at the constructor of this class i execute the AfxConnectionAdvise
> method:

> > >   BOOL Ret = ::AfxConnectionAdvise(
> > >      m_pRepTimer,
> > >      DIID___ciTimer,
> > >      GetIDispatch(FALSE), //get the IDispatch assocaiated with
> > > CServiceManagerDlg...
> > >      FALSE, //donod addref
> > >      &dwCookie );//cookie to break connection later...

> > > so in MFC application the sink is working and in ATL service it failed
> and
> > i
> > > don't know why.

> > > I tried another test, the same class using ATL instead of MFC :
> > > class CNotifyEvents :
> > >   public IDispatchImpl<__ciTimer, &DIID___ciTimer,
> > >    &CLSID_ciTimer>,
> > >   public CComObjectRoot

> > > and instead of AfxConnectionAdvise i used :

> > >    HRESULT hr=AtlAdvise(m_pRepTimer,
> > >     GetUnknown(),
> > >     DIID___ciTimer,
> > >     &dwCookie);

> > You call AtlAdvise from within a CNotifyEvents instance method?
Otherwise
> > there will be no GetUnknown() method to call.
> > What is the hr value.

> > > I think that my Major problem is at the second parameter GetUnknown()
> ( or
> > > in the first case, the third parameter :  GetIDispatch(FALSE) )  that
> > failes
> > > in ATL service, can somebody help me to know how can i establish sink
> > event
> > > in NON-WINDOWS environment ?
> > > Is there any special solution for ATL service?

> > What do you mean by establish a sink event in a NON-WINDOWS
environment???

> > Bye,
> > Sven



Sat, 28 Aug 2004 01:08:39 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll

Hi Ofir,

too fast - I thought you were just asking me by mail so I wrote back by mail without keeping a copy of the reply. To keep all the content in this thread, maybe you could just insert my mail content here.

Thanx,
Sven

  Hi Sven,

  I want to thank you very much for all your help, i completed the first step and the atl class for the sink event is working (a little different way that i found on the MSDN - you can see it on the attachements) on the test, and i learned a lot about my mistakes from your explanations.

  So now i have got the class for the sink event and the way to work with it, but on the test.

  I have read a lot of information about the ATL service (it's my first time with services) on the MSDN, but i have got two types of problems with it:
      1. i don't know how to debug it at the first time that i am starting the service, because just after the first time it's running (and get stuck...) i am able to select             "DEBUG" from the drop down of the Task Manager Processes list  of windows and to set breakpoints in the events. but because it's already ran the major             functions that i plan to debug, it's not useful.

      2. I am not sure that i know where to put the appropriate methods in the CServiceModule class that the wizard produce for me, but anyway, what i tried did not         work:

         (***)  i was able to define it only as global :
          CComObject<CNotifyEvents> *NotifyEventObj;

          because this include : #include <atlcom.h> ( for the usage of CComObject in the definition  
                  CComObject<CNotifyEvents> *NotifyEventObj;
          requires the definition of  _Module :
              CServiceModule _Module;
          I did not find other solution how to define it - CComObject<CNotifyEvents> *NotifyEventObj; - as member of my CNotifyEvents class

          (***)   i wrote this code at the end of the ServiceMain function, it suppose to create an instance (if it has not been created yet) and to execute the InitiateReplication function         that suppose to do some database connection job and to execute the AtlAdvise

   if (NotifyEventObj==NULL)
   {
    hr=NotifyEventObj->CreateInstance(&NotifyEventObj);
    if (FAILED(hr))
    {
     delete NotifyEventObj;
    }
    else
    {
     NotifyEventObj->InitiateReplication();
    }
   }
   StartSync();

          (***)  I wrote this code inline the Handler function.
              i need it to do the following in case that the user stop the service or start it :        
  inline void CServiceModule::Handler(DWORD dwOpcode)
  {
      switch (dwOpcode)
      {
      case SERVICE_CONTROL_STOP:
          SetServiceStatus(SERVICE_STOP_PENDING);
          PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
    StartSync();
    //DistroyReplication();
          break;
      case SERVICE_CONTROL_PAUSE:
    //StopSync();
          break;
      case SERVICE_CONTROL_CONTINUE:
    StartSync();
          break;
      case SERVICE_CONTROL_INTERROGATE:
          break;
      case SERVICE_CONTROL_SHUTDOWN:
    StopSync();
          break;
      default:
          LogEvent(_T("Bad service request"));
      }
  }

  when this two functions content is :

  void CServiceModule::StartSync()
  {
   NotifyEventObj->StartTimer();
  }

  void CServiceModule::StopSync()
  {
   NotifyEventObj->StopTimer();
  }

  Thank you for any help,
  Ofir


  > Hi,
  >
  > I had a look at your attachments.
  >
  > You are calling AtlAdvise from within your constructor: m_pReqTimer is still
  > NULL at that time.
  > InitiateReplication is a far better place. What's your problem with calling
  > AtlAdvise at that point?
  >
  > GetIDispatch is a helper function from MFC's CCmdTarget to get the
  > corresponding IDispatch interface from an CCmdTarget derived class - it's
  > just not available if don't use MFC to implement your COM object. In ATL you
  > should use GetUnknown().
  >
  > What's still missing is how do you create an instance of CNotifyEvents? It
  > should be:
  >
  > CComObject<CNotifyEvents> *p = NULL;
  > HRESULT hr = p->CreateInstance(&p);
  > if(FAILED(hr))
  > {
  >    // ouch
  >    delete p;
  > }
  > else
  > {
  >    p->InitiateReplication();
  > }
  >
  > Bye,
  > Sven
  >


  > > Hi Sven,
  > >
  > > You call AtlAdvise from within a CNotifyEvents instance method?
  > >
  > > --yes, i am doing so, why? it did work at the first test when i used
  > > AfxConnectionAdvise.
  > > --is there difference in the location of  AfxConnectionAdvise and
  > AtlAdvise
  > > ?
  > >
  > > What is the hr value?
  > >
  > > -- in the service i don't know, because i don't know how to debug it on
  > the
  > > first time, before it creates the process, and it create a process for it
  > > -- just after the the execution of the Start of the service
  > > -- i know that the problem is there because when i remove the AtlAdvise it
  > > does not fail.
  > >
  > > -- the AtlAdvice failed also in the MFC application test, and i have no
  > idea
  > > why
  > > -- I get the message box  : "Runtime error - R6025 - pure virtual function
  > > call"  , with Abord/Retry/Ignore buttons, and when i press Retry i get to
  > > \VC98\CRT\SRC\CRTOMSG.C to the lines :
  > >
  > >             if (rterrnum != _RT_CRNL)
  > >             {
  > >                 if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL,
  > > rterrs[tblindx].rterrtxt))
  > >                     _CrtDbgBreak();
  > >             }
  > >
  > > So i don't know why it failes.
  > >
  > > I did not find any example of service with sink event on the MSDN and i
  > > don't understand what is the problem
  > > I am attaching  a zip file of the two classes of the tests (CNotify,
  > > CNotifyEvent) in case that it is interesting you.
  > > the CNotify class is working on MFC Application but does not work on ATL
  > > service
  > > the CNotifyEvent class does not working on both.
  > >
  > >
  > > > What do you mean by establish a sink event in a NON-WINDOWS
  > environment???
  > >
  > > I am not sure, but as much as i understood the Advise functions expect to
  > > get an IUnknown pointer to a window interface that suppose to be able to
  > > handle/accept messages, and in the case of  the AtlService i don't think
  > > that i have one.
  > > so can you please tell me which IUnknown suppose to be the client's
  > IUnknown
  > > (in my case my class CNotifyEvents suppose to handle the sink) in case of
  > > ATL service ?
  > > Do you have any basice example of the usage of Sink in the ATL service ? I
  > > will be thankful for that.
  > >
  > >
  > > Thank you for the help Sven,
  > >
  > > Ofir

  > >
  > >


  > > > Hi,
  > > >
  > > > see inline:
  > > >


  > > > > Hi,
  > > > >
  > > > > I have an ActiveX dll with a connection point, and i need to use it in
  > > the
  > > > > ATL service.
  > > > > I tried to create and mfc based class ( class CNotify : public
  > > > CCmdTarget )
  > > > > with the appropriate definitions for the sink event:
  > > > >
  > > > > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget)
  > > > >  DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY,
  > > > > VTS_R8)
  > > > > END_DISPATCH_MAP( )
  > > > >
  > > > > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget)
  > > > >  INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch)
  > > > > END_INTERFACE_MAP()
  > > > >
  > > > > (this class is in test use in MFC application and the sink event is
  > > > working)
  > > > >
  > > > > at the constructor of this class i execute the AfxConnectionAdvise
  > > method:
  > > > >
  > > > >   BOOL Ret = ::AfxConnectionAdvise(
  > > > >      m_pRepTimer,
  > > > >      DIID___ciTimer,
  > > > >      GetIDispatch(FALSE), //get the IDispatch assocaiated with
  > > > > CServiceManagerDlg...
  > > > >      FALSE, //donod addref
  > > > >      &dwCookie );//cookie to break connection later...
  > > > >
  > > > >
  > > > > so in MFC application the sink is working and in ATL service it failed
  > > and
  > > > i
  > > > > don't know why.
  > > > >
  > > > > I tried another test, the same class using ATL instead of MFC :
  > > > > class CNotifyEvents :
  > > > >   public IDispatchImpl<__ciTimer, &DIID___ciTimer,
  > > > >    &CLSID_ciTimer>,
  > > > >   public CComObjectRoot
  > > > >
  > > > > and instead of AfxConnectionAdvise i used :
  > > > >
  > > > >    HRESULT hr=AtlAdvise(m_pRepTimer,
  > > > >     GetUnknown(),
  > > > >     DIID___ciTimer,
  > > > >     &dwCookie);
  > > >
  > > > You call AtlAdvise from within a CNotifyEvents instance method?
  > Otherwise
  > > > there will be no GetUnknown() method to call.
  > > > What is the hr value.
  > > >
  > > > > I think that my Major problem is at the second parameter GetUnknown()
  > > ( or
  > > > > in the first case, the third parameter :  GetIDispatch(FALSE) )  that
  > > > failes
  > > > > in ATL service, can somebody help me to know how can i establish sink
  > > > event
  > > > > in NON-WINDOWS environment ?
  > > > > Is there any special solution for ATL service?
  > > >
  > > > What do you mean by establish a sink event in a NON-WINDOWS
  > environment???
  > > >
  > > > Bye,
  > > > Sven
  > > >
  > > >
  > > >
  > >
  > >
  > >
  >
  >



Sun, 29 Aug 2004 01:09:48 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll

Hi Svan,

Thank you again for your great help and tips.

(This mail is already on the news groups vc.atl)

Finally i am able to debug the service and i must say that it's thanks to you.
As you asked me to, i put the line : MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY);
in the _tWinMain just before the line : _Module.Start();

I see that i failed in the Run() function on the method CoInitializeSecurity.
the HRESULT that i get there is :
-2147417831 (80010119) Security must be initialized before any
interfaces are marshalled or unmarshalled. It
cannot be changed once initialized.
There is information about it on the MSDN :
INFO: Translating Automation Errors for VB/VBA (Long) , ID: Q186063
So i commented this lines out and now the "start service" actually working:
/*
CSecurityDescriptor sd;
sd.InitializeFromThreadToken();
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
_ASSERTE(SUCCEEDED(hr));
*/
There is solution for it without excluding this code? how important is this security issue?

Now when i stop the service and i debug it, i see that when i stop the sevice, it's try to execute the StopTimer() method of the component (that actually tells it to stop raising the Notify event in the CNotifyEvents class of the service) it probably fialed and distroy the NotifyEventObj object. I tried to catch the error, but i don't know why it ignore any TRY-CATCH that i put, anyway i don't get any failure message at this point. I also though that the reason for this failure is the CoInitialize and CoUninitialize in the CServiceModule::Run(), but after i removed it nothing changed, the problem is still there.

I also tried to understand the smart pointer idea, but i did not really understand it. in my case, the class CNotifyEvents had no interface id - INotifyEvents (as much as i know), and i don't suppose to expose one because this class suppose to be completely internal for catching the sink event and handling it. please correct me if i misunderstand you.

Best regards,
Ofir

Hi Ofir,

1) to Debug a service from the start I like the following contruct:
inside WinMain or ServiceMain:
... // some code
MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY);
... // the code I wan't to debug
When the service starts it will display the messagebox
(MB_DEFAULT_DESKTOP_ONLY does the trick!).
Now you can attach the de{*filter*} to the service. Put a breakpoint right after
the MessageBox call and start debugging.
2) You could store a smart pointer to IUnknown or another interface exposed
by CNotifyEvents in your CServiceModule: CComPtr<INotifyEvents>
m_spNotifyEvents.
In Run() or Start() of your CServiceModule you can then use
CComObject<CNotifyEvents> *p just locally to create the instance and store
an interface pointer in your smart pointer member with a call to
p->QueryInterface(&m_spNotifyEvents). This would also handle ref counting
automatically.
I hope I got alll your questions.
Bye,
Sven

  Hi Ofir,

  too fast - I thought you were just asking me by mail so I wrote back by mail without keeping a copy of the reply. To keep all the content in this thread, maybe you could just insert my mail content here.

  Thanx,
  Sven

    Hi Sven,

    I want to thank you very much for all your help, i completed the first step and the atl class for the sink event is working (a little different way that i found on the MSDN - you can see it on the attachements) on the test, and i learned a lot about my mistakes from your explanations.

    So now i have got the class for the sink event and the way to work with it, but on the test.

    I have read a lot of information about the ATL service (it's my first time with services) on the MSDN, but i have got two types of problems with it:
        1. i don't know how to debug it at the first time that i am starting the service, because just after the first time it's running (and get stuck...) i am able to select             "DEBUG" from the drop down of the Task Manager Processes list  of windows and to set breakpoints in the events. but because it's already ran the major             functions that i plan to debug, it's not useful.

        2. I am not sure that i know where to put the appropriate methods in the CServiceModule class that the wizard produce for me, but anyway, what i tried did not         work:

           (***)  i was able to define it only as global :
            CComObject<CNotifyEvents> *NotifyEventObj;

            because this include : #include <atlcom.h> ( for the usage of CComObject in the definition  
                    CComObject<CNotifyEvents> *NotifyEventObj;
            requires the definition of  _Module :
                CServiceModule _Module;
            I did not find other solution how to define it - CComObject<CNotifyEvents> *NotifyEventObj; - as member of my CNotifyEvents class

            (***)   i wrote this code at the end of the ServiceMain function, it suppose to create an instance (if it has not been created yet) and to execute the InitiateReplication function         that suppose to do some database connection job and to execute the AtlAdvise

     if (NotifyEventObj==NULL)
     {
      hr=NotifyEventObj->CreateInstance(&NotifyEventObj);
      if (FAILED(hr))
      {
       delete NotifyEventObj;
      }
      else
      {
       NotifyEventObj->InitiateReplication();
      }
     }
     StartSync();

            (***)  I wrote this code inline the Handler function.
                i need it to do the following in case that the user stop the service or start it :        
    inline void CServiceModule::Handler(DWORD dwOpcode)
    {
        switch (dwOpcode)
        {
        case SERVICE_CONTROL_STOP:
            SetServiceStatus(SERVICE_STOP_PENDING);
            PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
      StartSync();
      //DistroyReplication();
            break;
        case SERVICE_CONTROL_PAUSE:
      //StopSync();
            break;
        case SERVICE_CONTROL_CONTINUE:
      StartSync();
            break;
        case SERVICE_CONTROL_INTERROGATE:
            break;
        case SERVICE_CONTROL_SHUTDOWN:
      StopSync();
            break;
        default:
            LogEvent(_T("Bad service request"));
        }
    }

    when this two functions content is :

    void CServiceModule::StartSync()
    {
     NotifyEventObj->StartTimer();
    }

    void CServiceModule::StopSync()
    {
     NotifyEventObj->StopTimer();
    }

    Thank you for any help,
    Ofir


    > Hi,
    >
    > I had a look at your attachments.
    >
    > You are calling AtlAdvise from within your constructor: m_pReqTimer is still
    > NULL at that time.
    > InitiateReplication is a far better place. What's your problem with calling
    > AtlAdvise at that point?
    >
    > GetIDispatch is a helper function from MFC's CCmdTarget to get the
    > corresponding IDispatch interface from an CCmdTarget derived class - it's
    > just not available if don't use MFC to implement your COM object. In ATL you
    > should use GetUnknown().
    >
    > What's still missing is how do you create an instance of CNotifyEvents? It
    > should be:
    >
    > CComObject<CNotifyEvents> *p = NULL;
    > HRESULT hr = p->CreateInstance(&p);
    > if(FAILED(hr))
    > {
    >    // ouch
    >    delete p;
    > }
    > else
    > {
    >    p->InitiateReplication();
    > }
    >
    > Bye,
    > Sven
    >


    > > Hi Sven,
    > >
    > > You call AtlAdvise from within a CNotifyEvents instance method?
    > >
    > > --yes, i am doing so, why? it did work at the first test when i used
    > > AfxConnectionAdvise.
    > > --is there difference in the location of  AfxConnectionAdvise and
    > AtlAdvise
    > > ?
    > >
    > > What is the hr value?
    > >
    > > -- in the service i don't know, because i don't know how to debug it on
    > the
    > > first time, before it creates the process, and it create a process for it
    > > -- just after the the execution of the Start of the service
    > > -- i know that the problem is there because when i remove the AtlAdvise it
    > > does not fail.
    > >
    > > -- the AtlAdvice failed also in the MFC application test, and i have no
    > idea
    > > why
    > > -- I get the message box  : "Runtime error - R6025 - pure virtual function
    > > call"  , with Abord/Retry/Ignore buttons, and when i press Retry i get to
    > > \VC98\CRT\SRC\CRTOMSG.C to the lines :
    > >
    > >             if (rterrnum != _RT_CRNL)
    > >             {
    > >                 if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL,
    > > rterrs[tblindx].rterrtxt))
    > >                     _CrtDbgBreak();
    > >             }
    > >
    > > So i don't know why it failes.
    > >
    > > I did not find any example of service with sink event on the MSDN and i
    > > don't understand what is the problem
    > > I am attaching  a zip file of the two classes of the tests (CNotify,
    > > CNotifyEvent) in case that it is interesting you.
    > > the CNotify class is working on MFC Application but does not work on ATL
    > > service
    > > the CNotifyEvent class does not working on both.
    > >
    > >
    > > > What do you mean by establish a sink event in a NON-WINDOWS
    > environment???
    > >
    > > I am not sure, but as much as i understood the Advise functions expect to
    > > get an IUnknown pointer to a window interface that suppose to be able to
    > > handle/accept messages, and in the case of  the
...

read more »



Sun, 29 Aug 2004 20:32:15 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll

Hi,


  Hi Svan,

  Thank you again for your great help and tips.

  (This mail is already on the news groups vc.atl)

  Finally i am able to debug the service and i must say that it's thanks to you.
  As you asked me to, i put the line : MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY);
  in the _tWinMain just before the line : _Module.Start();

  I see that i failed in the Run() function on the method CoInitializeSecurity.
  the HRESULT that i get there is :
  -2147417831 (80010119) Security must be initialized before any
  interfaces are marshalled or unmarshalled. It
  cannot be changed once initialized.
  There is information about it on the MSDN :
  INFO: Translating Automation Errors for VB/VBA (Long) , ID: Q186063
  So i commented this lines out and now the "start service" actually working:
  /*
  CSecurityDescriptor sd;
  sd.InitializeFromThreadToken();
  hr = CoInitializeSecurity(sd, -1, NULL, NULL,
  RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
  _ASSERTE(SUCCEEDED(hr));
  */
  There is solution for it without excluding this code? how important is this security issue?

Of course: create your CNotifyEvent object *after* you called CoInitializeSecurity.

  Now when i stop the service and i debug it, i see that when i stop the sevice, it's try to execute the StopTimer() method of the component (that actually tells it to stop raising the Notify event in the CNotifyEvents class of the service) it probably fialed and distroy the NotifyEventObj object. I tried to catch the error, but i don't know why it ignore any TRY-CATCH that i put, anyway i don't get any failure message at this point. I also though that the reason for this failure is the CoInitialize and CoUninitialize in the CServiceModule::Run(), but after i removed it nothing changed, the problem is still there.

Do *not* remove CoInitialize and CoUninitialize from the Run method. That should break your COM calls - if not I'm not sure if I should call you /lucky/, I guess not: Somebody could have called CoInitialize in that thread - which should be in the exe's responsibility, i.d. your responsibility - maybe this /someone/ calls CoUninitialize at another point - breaking your COM calls then.

Well catch can only catch what you tell it to catch. If some other type is thrown it will cause an uncaught exception:

try
{
   TheBadFunc();

Quote:
}

catch(_com_error &e1)  // produced by #import generated code
{
   catch _com_error instances}
Quote:
}

catch(CException* e2) // produced by MFC code
{
   catch MFC specific errors
Quote:
}

catch(...)
{
   catch everything else - like e.g. access violation...

Quote:
}

From your mailed code I saw that you once you caught _com_error& and once CException*. But what to catch depends on the classes/methods you use. So if you don't use MFC CExeption* will be of no use. if there are bugs around you could try to catch(...) or if you don't catch it and have debug builds you could watch the call stack to get a clue where the exception was generated.

  I also tried to understand the smart pointer idea, but i did not really understand it. in my case, the class CNotifyEvents had no interface id - INotifyEvents (as much as i know), and i don't suppose to expose one because this class suppose to be completely internal for catching the sink event and handling it. please correct me if i misunderstand you.

As a sink it has to expose at least one interface: the one your event provider will call you on. That seems to be IDispatch, so instead of CComObject<CNotifyEvent> *Global_Object you could use CComPtr<IDispatch> m_spServiceModuleMember.
  Best regards,
  Ofir

HTH,
Sven

  Hi Ofir,

  1) to Debug a service from the start I like the following contruct:
  inside WinMain or ServiceMain:
  ... // some code
  MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY);
  ... // the code I wan't to debug
  When the service starts it will display the messagebox
  (MB_DEFAULT_DESKTOP_ONLY does the trick!).
  Now you can attach the de{*filter*} to the service. Put a breakpoint right after
  the MessageBox call and start debugging.
  2) You could store a smart pointer to IUnknown or another interface exposed
  by CNotifyEvents in your CServiceModule: CComPtr<INotifyEvents>
  m_spNotifyEvents.
  In Run() or Start() of your CServiceModule you can then use
  CComObject<CNotifyEvents> *p just locally to create the instance and store
  an interface pointer in your smart pointer member with a call to
  p->QueryInterface(&m_spNotifyEvents). This would also handle ref counting
  automatically.
  I hope I got alll your questions.
  Bye,
  Sven

    Hi Ofir,

    too fast - I thought you were just asking me by mail so I wrote back by mail without keeping a copy of the reply. To keep all the content in this thread, maybe you could just insert my mail content here.

    Thanx,
    Sven

      Hi Sven,

      I want to thank you very much for all your help, i completed the first step and the atl class for the sink event is working (a little different way that i found on the MSDN - you can see it on the attachements) on the test, and i learned a lot about my mistakes from your explanations.

      So now i have got the class for the sink event and the way to work with it, but on the test.

      I have read a lot of information about the ATL service (it's my first time with services) on the MSDN, but i have got two types of problems with it:
          1. i don't know how to debug it at the first time that i am starting the service, because just after the first time it's running (and get stuck...) i am able to select             "DEBUG" from the drop down of the Task Manager Processes list  of windows and to set breakpoints in the events. but because it's already ran the major             functions that i plan to debug, it's not useful.

          2. I am not sure that i know where to put the appropriate methods in the CServiceModule class that the wizard produce for me, but anyway, what i tried did not         work:

             (***)  i was able to define it only as global :
              CComObject<CNotifyEvents> *NotifyEventObj;

              because this include : #include <atlcom.h> ( for the usage of CComObject in the definition  
                      CComObject<CNotifyEvents> *NotifyEventObj;
              requires the definition of  _Module :
                  CServiceModule _Module;
              I did not find other solution how to define it - CComObject<CNotifyEvents> *NotifyEventObj; - as member of my CNotifyEvents class

              (***)   i wrote this code at the end of the ServiceMain function, it suppose to create an instance (if it has not been created yet) and to execute the InitiateReplication function         that suppose to do some database connection job and to execute the AtlAdvise

       if (NotifyEventObj==NULL)
       {
        hr=NotifyEventObj->CreateInstance(&NotifyEventObj);
        if (FAILED(hr))
        {
         delete NotifyEventObj;
        }
        else
        {
         NotifyEventObj->InitiateReplication();
        }
       }
       StartSync();

              (***)  I wrote this code inline the Handler function.
                  i need it to do the following in case that the user stop the service or start it :        
      inline void CServiceModule::Handler(DWORD dwOpcode)
      {
          switch (dwOpcode)
          {
          case SERVICE_CONTROL_STOP:
              SetServiceStatus(SERVICE_STOP_PENDING);
              PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        StartSync();
        //DistroyReplication();
              break;
          case SERVICE_CONTROL_PAUSE:
        //StopSync();
              break;
          case SERVICE_CONTROL_CONTINUE:
        StartSync();
              break;
          case SERVICE_CONTROL_INTERROGATE:
              break;
          case SERVICE_CONTROL_SHUTDOWN:
        StopSync();
              break;
          default:
              LogEvent(_T("Bad service request"));
          }
      }

      when this two functions content is :

      void CServiceModule::StartSync()
      {
       NotifyEventObj->StartTimer();
      }

      void CServiceModule::StopSync()
      {
       NotifyEventObj->StopTimer();
      }

      Thank you for any help,
      Ofir


      > Hi,
      >
      > I had a look at your attachments.
      >
      > You are calling AtlAdvise from within your constructor: m_pReqTimer is still
      > NULL at that time.
      > InitiateReplication is a far better place. What's your problem with calling
      > AtlAdvise at that point?
      >
      > GetIDispatch is a helper function from MFC's CCmdTarget to get the
      > corresponding IDispatch interface from an CCmdTarget derived class - it's
      > just not available if don't use MFC to implement your COM object. In ATL you
      > should use GetUnknown().
      >
      > What's still missing is how do you create an instance of CNotifyEvents? It
      > should be:
      >
      > CComObject<CNotifyEvents> *p = NULL;
      > HRESULT hr = p->CreateInstance(&p);
      > if(FAILED(hr))
      > {
      >    // ouch
      >    delete p;
      > }
      > else
      > {
      >    p->InitiateReplication();
      > }
      >
      > Bye,
      > Sven
      >


      > > Hi Sven,
      > >
      > > You call AtlAdvise from within a CNotifyEvents instance method?
      > >
      > > --yes, i am doing so, why? it did work at the first test
...

read more »



Sun, 29 Aug 2004 21:16:42 GMT  
 ATL Service - Need to establish sink for a connection point of ActiveX dll

Hi,

glad to here that!

You're welcome,
Sven



Sun, 29 Aug 2004 23:12:46 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. ATL DLL event sink with a VB ActiveX DLL event source

2. Connection points between a VB COM-based and ATL COM-based (NT Service) MTA

3. ATL Com wrapper for C DLL - problem with Connection Points

4. ATL Consumer Classes - How to establish connection?

5. c# connection point sink

6. Connection Points - firing an event to a sink in another process

7. Connection Point / Sink and DoModal

8. connection point handler sink in jscript?

9. Control Events Myth - Advise Sink vs Connection Point?

10. Looking for a sample C# client which sinks to COM event connection point

11. Atl NT service calling VB ActiveX dll had problem when clean-up

12. Problem in using VB Activex dll in Atl service

 

 
Powered by phpBB® Forum Software