Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. ATL compiler error

ATL compiler error

Scheduled Pinned Locked Moved C / C++ / MFC
c++helpquestion
16 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Roger Stoltz

    DavidCrow wrote:

    a .idl file was created and it has a GUID in it for the IMyEventHandler interface.

    David, I don't get exactly what you're trying to do. It seems like you're trying to create COM server and register something else that you have developed (CMyEventHandler?) for receiving COM events. Right? What I'm trying to figure out is why you're trying to create an instance of your CMyEventhandler... Is it really a COM server? If so, from where is it created and does the header files created have a CLSID for it? Usually you would create a COM server with e.g. ::CoCreateInstance(), or one of its equivalents. You provide the CLSID for the server, the IID for the desired interface and a pointer to store the interface pointer in if the call was successful. If the server produces COM events that the client is interested in, the client uses a mechanism in the server to register itself as an event listener (Advise()?). From your explanation I don't see the above happening, a part from calling CreateInstance but for what looks to me as the "wrong" object. Can you elaborate on this a bit further David?

    "It's supposed to be hard, otherwise anybody could do it!" - selfquote
    "High speed never compensates for wrong direction!" - unknown

    D Offline
    D Offline
    David Crow
    wrote on last edited by
    #5

    Roger Stoltz wrote:

    David, I don't get exactly what you're trying to do. It seems like you're trying to create COM server and register something else that you have developed (CMyEventHandler?) for receiving COM events. Right?

    My overall intent is to open a .mp3 file using the Windows Media Player COM object, and then read some information from one of the headers. I can't get this information until the player has loaded the .mp3 file. A side effect of loading the .mp3 file is that it will start playing it. To get around this, I need to respond to the 'play' event and stop it. That's what got me to looking at the IWMPEvents interface.

    Roger Stoltz wrote:

    What I'm trying to figure out is why you're trying to create an instance of your CMyEventhandler... Is it really a COM server? If so, from where is it created and does the header files created have a CLSID for it? Usually you would create a COM server with e.g. ::CoCreateInstance(), or one of its equivalents. You provide the CLSID for the server, the IID for the desired interface and a pointer to store the interface pointer in if the call was successful. If the server produces COM events that the client is interested in, the client uses a mechanism in the server to register itself as an event listener (Advise()?). From your explanation I don't see the above happening, a part from calling CreateInstance but for what looks to me as the "wrong" object. Can you elaborate on this a bit further David?

    Good questions. As I've done very little with COM, some of the terms and procedures are still a mystery. Other pieces of my code look like:

    CComPtr<IWMPPlayer4> player;
    HRESULT hr = player.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);

    CComPtr<IConnectionPoint> connectionPoint;
    CComPtr<IConnectionPointContainer> connectionContainer;
    player->QueryInterface(&connectionContainer);
    connectionContainer->FindConnectionPoint(__uuidof(IWMPEvents), &connectionPoint);

    "One man's wage rise is another man's price increase." - Harold Wilson

    "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

    "Man who follows car will be exhausted." - Confucius

    R 1 Reply Last reply
    0
    • D David Crow

      Roger Stoltz wrote:

      David, I don't get exactly what you're trying to do. It seems like you're trying to create COM server and register something else that you have developed (CMyEventHandler?) for receiving COM events. Right?

      My overall intent is to open a .mp3 file using the Windows Media Player COM object, and then read some information from one of the headers. I can't get this information until the player has loaded the .mp3 file. A side effect of loading the .mp3 file is that it will start playing it. To get around this, I need to respond to the 'play' event and stop it. That's what got me to looking at the IWMPEvents interface.

      Roger Stoltz wrote:

      What I'm trying to figure out is why you're trying to create an instance of your CMyEventhandler... Is it really a COM server? If so, from where is it created and does the header files created have a CLSID for it? Usually you would create a COM server with e.g. ::CoCreateInstance(), or one of its equivalents. You provide the CLSID for the server, the IID for the desired interface and a pointer to store the interface pointer in if the call was successful. If the server produces COM events that the client is interested in, the client uses a mechanism in the server to register itself as an event listener (Advise()?). From your explanation I don't see the above happening, a part from calling CreateInstance but for what looks to me as the "wrong" object. Can you elaborate on this a bit further David?

      Good questions. As I've done very little with COM, some of the terms and procedures are still a mystery. Other pieces of my code look like:

      CComPtr<IWMPPlayer4> player;
      HRESULT hr = player.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);

      CComPtr<IConnectionPoint> connectionPoint;
      CComPtr<IConnectionPointContainer> connectionContainer;
      player->QueryInterface(&connectionContainer);
      connectionContainer->FindConnectionPoint(__uuidof(IWMPEvents), &connectionPoint);

      "One man's wage rise is another man's price increase." - Harold Wilson

      "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

      "Man who follows car will be exhausted." - Confucius

      R Offline
      R Offline
      Roger Stoltz
      wrote on last edited by
      #6

      DavidCrow wrote:

      My overall intent is to open a .mp3 file using the Windows Media Player COM object, and then read some information from one of the headers.

      Perhaps this is not what you'd like to hear/read, but wouldn't it suffice to read the mp3 file from your application if you're only interested in the header? I guess you've thought about this alternative already and discarded it. If not, you may find this[^] or this[^] useful. I don't know what header information you're looking for. More about the Media Player solution... Have you had a look at this article[^] about handling Media Player events in C++? Provided that you successfully can create the Media Player server, you should be able to find something in the article above that you can use. You should also have a look at the ATL sample that demonstrates connection points: ATLDuck.

      "It's supposed to be hard, otherwise anybody could do it!" - selfquote
      "High speed never compensates for wrong direction!" - unknown

      D 1 Reply Last reply
      0
      • R Roger Stoltz

        DavidCrow wrote:

        My overall intent is to open a .mp3 file using the Windows Media Player COM object, and then read some information from one of the headers.

        Perhaps this is not what you'd like to hear/read, but wouldn't it suffice to read the mp3 file from your application if you're only interested in the header? I guess you've thought about this alternative already and discarded it. If not, you may find this[^] or this[^] useful. I don't know what header information you're looking for. More about the Media Player solution... Have you had a look at this article[^] about handling Media Player events in C++? Provided that you successfully can create the Media Player server, you should be able to find something in the article above that you can use. You should also have a look at the ATL sample that demonstrates connection points: ATLDuck.

        "It's supposed to be hard, otherwise anybody could do it!" - selfquote
        "High speed never compensates for wrong direction!" - unknown

        D Offline
        D Offline
        David Crow
        wrote on last edited by
        #7

        Roger Stoltz wrote:

        Have you had a look at this article[^] about handling Media Player events in C++?

        Yes, several times.

        Roger Stoltz wrote:

        Provided that you successfully can create the Media Player server, you should be able to find something in the article above that you can use.

        I can play the .mp3 file just fine. I can also change other settings (e.g., auto start). It's just getting past the "no GUID specified" compiler error that's troubling me.

        "One man's wage rise is another man's price increase." - Harold Wilson

        "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

        "Man who follows car will be exhausted." - Confucius

        R 1 Reply Last reply
        0
        • D David Crow

          Roger Stoltz wrote:

          Have you had a look at this article[^] about handling Media Player events in C++?

          Yes, several times.

          Roger Stoltz wrote:

          Provided that you successfully can create the Media Player server, you should be able to find something in the article above that you can use.

          I can play the .mp3 file just fine. I can also change other settings (e.g., auto start). It's just getting past the "no GUID specified" compiler error that's troubling me.

          "One man's wage rise is another man's price increase." - Harold Wilson

          "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

          "Man who follows car will be exhausted." - Confucius

          R Offline
          R Offline
          Roger Stoltz
          wrote on last edited by
          #8

          DavidCrow wrote:

          It's just getting notified of events that's troubling me.

          Okay... Basically this is what you have to do:

          1. Implement a class that derives from the event interface you're interested in and put the interface in the COM_MAP. As I understand it you've already done this part.
          2. When you've successfully created the Media Player server and got an interface pointer (IWMPPlayer), you create an instance of the class mentioned above; not by using CreateInstance(), use new or similar (you know what I mean).
          3. Ask IWMPPlayer for the IConnectionPointContainer interface as described in the article.
          4. Find the connection point you want, IWMPEvents, by calling IConnectionPointContainer::FindConnectionPoint() and you should get an IConnectionPoint interface in return as described in the article.
          5. Register your class as an event listener by calling IConnectionPoint::Advise() and provide a pointer to your instance of your CMyEventHandler. Store the cookie and the IConnectionPoint interface pointer as you'll need it when you unregister from the server.
          6. You should be all set to catch events from Media Player!
          7. Remember to call IConnectionPoint::Unadvise() when you're done.

          The ATLDuck sample[^] explains how to set up connection point further. It gives you a complete working example and not just some code snippets.

          "It's supposed to be hard, otherwise anybody could do it!" - selfquote
          "High speed never compensates for wrong direction!" - unknown

          D 1 Reply Last reply
          0
          • R Roger Stoltz

            DavidCrow wrote:

            It's just getting notified of events that's troubling me.

            Okay... Basically this is what you have to do:

            1. Implement a class that derives from the event interface you're interested in and put the interface in the COM_MAP. As I understand it you've already done this part.
            2. When you've successfully created the Media Player server and got an interface pointer (IWMPPlayer), you create an instance of the class mentioned above; not by using CreateInstance(), use new or similar (you know what I mean).
            3. Ask IWMPPlayer for the IConnectionPointContainer interface as described in the article.
            4. Find the connection point you want, IWMPEvents, by calling IConnectionPointContainer::FindConnectionPoint() and you should get an IConnectionPoint interface in return as described in the article.
            5. Register your class as an event listener by calling IConnectionPoint::Advise() and provide a pointer to your instance of your CMyEventHandler. Store the cookie and the IConnectionPoint interface pointer as you'll need it when you unregister from the server.
            6. You should be all set to catch events from Media Player!
            7. Remember to call IConnectionPoint::Unadvise() when you're done.

            The ATLDuck sample[^] explains how to set up connection point further. It gives you a complete working example and not just some code snippets.

            "It's supposed to be hard, otherwise anybody could do it!" - selfquote
            "High speed never compensates for wrong direction!" - unknown

            D Offline
            D Offline
            David Crow
            wrote on last edited by
            #9

            It appears that I have steps 1-5 in place. Do you agree? Does the duck sample talk about how to avoid the GUID error that I'm battling?

            "One man's wage rise is another man's price increase." - Harold Wilson

            "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

            "Man who follows car will be exhausted." - Confucius

            R 1 Reply Last reply
            0
            • D David Crow

              It appears that I have steps 1-5 in place. Do you agree? Does the duck sample talk about how to avoid the GUID error that I'm battling?

              "One man's wage rise is another man's price increase." - Harold Wilson

              "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

              "Man who follows car will be exhausted." - Confucius

              R Offline
              R Offline
              Roger Stoltz
              wrote on last edited by
              #10

              DavidCrow wrote:

              It appears that I have steps 1-5 in place. Do you agree?

              Nope, I don't agree. Not unless you've altered the code you presented earlier where you tried to create an instance of CMyEventHandler by calling CreateInstance() into what I suggested, e.g. using new.

              DavidCrow wrote:

              Does the duck sample talk about how to avoid the GUID error that I'm battling?

              Nope. The question is irrelevant as a CLSID for CMyEventHandler won't be needed when you create a CMyEventHandler on the heap or the stack. Note that what the compiler complains about is a missing "Class ID", CLSID, since it refers to the 'object' CMyEventHandler. The CLSID is the identity of the server one is trying to create with a call to CreateInstance(). This is not the same as the identity of the interface you're trying to use called "Interface ID" or IID, which also has a Globally Unique IDentifier assigned to it. Your CMyEventHandler declaration should look something like this:

              class ATL_NO_VTABLE CMyEventHandler :
              public CComObjectRootEx<CComSingleThreadModel>,
              public IWMPEvents
              {
              public:
              BEGIN_COM_MAP( CMyEventHandler )
              COM_INTERFACE_ENTRY(IWMPEvents)
              END_COM_MAP()

              public:
              	/\* Here goes declarations of the functions in the IWMPEvents interface \*/
              

              };

              The code where you create the Media Player server should look something like this, as partially described in the article:

              CComPtr<IWMPPlayer> spWMPPlayer;
              CComPtr<IConnectionPoint> spConnectionPoint;
              DWORD dwAdviseCookie;
              HRESULT hr;

              /* I don't know the CLSID or ProgID of the Media Player server as I'm currently sitting on an
              ** Ubuntu machine at home, but let's just assume you've successfully created the Media Player
              ** server and you have a valid interface pointer for it: spWMPPlayer.
              ** Anyway you seem to have taken care of that already. ;-)
              */

              /* Create the CMyEventHandler object */
              CMyEventHandler* pMyEventHandler = new CComObject<CMyEventHandler>;

              /* Get the connection point */
              CComQIPtr<IConnectionPointContainer, &__uuidof(IConnectionPointContainer)> spConnectionContainer( spWMPPlayer );
              if( spConnectionContainer )
              {
              hr = spConnectionContainer->FindConnectionPoint( __uuidof(IWMPEvents), &spConnectionPoint )
              if( pMyEventHandler && SU

              D 1 Reply Last reply
              0
              • R Roger Stoltz

                DavidCrow wrote:

                It appears that I have steps 1-5 in place. Do you agree?

                Nope, I don't agree. Not unless you've altered the code you presented earlier where you tried to create an instance of CMyEventHandler by calling CreateInstance() into what I suggested, e.g. using new.

                DavidCrow wrote:

                Does the duck sample talk about how to avoid the GUID error that I'm battling?

                Nope. The question is irrelevant as a CLSID for CMyEventHandler won't be needed when you create a CMyEventHandler on the heap or the stack. Note that what the compiler complains about is a missing "Class ID", CLSID, since it refers to the 'object' CMyEventHandler. The CLSID is the identity of the server one is trying to create with a call to CreateInstance(). This is not the same as the identity of the interface you're trying to use called "Interface ID" or IID, which also has a Globally Unique IDentifier assigned to it. Your CMyEventHandler declaration should look something like this:

                class ATL_NO_VTABLE CMyEventHandler :
                public CComObjectRootEx<CComSingleThreadModel>,
                public IWMPEvents
                {
                public:
                BEGIN_COM_MAP( CMyEventHandler )
                COM_INTERFACE_ENTRY(IWMPEvents)
                END_COM_MAP()

                public:
                	/\* Here goes declarations of the functions in the IWMPEvents interface \*/
                

                };

                The code where you create the Media Player server should look something like this, as partially described in the article:

                CComPtr<IWMPPlayer> spWMPPlayer;
                CComPtr<IConnectionPoint> spConnectionPoint;
                DWORD dwAdviseCookie;
                HRESULT hr;

                /* I don't know the CLSID or ProgID of the Media Player server as I'm currently sitting on an
                ** Ubuntu machine at home, but let's just assume you've successfully created the Media Player
                ** server and you have a valid interface pointer for it: spWMPPlayer.
                ** Anyway you seem to have taken care of that already. ;-)
                */

                /* Create the CMyEventHandler object */
                CMyEventHandler* pMyEventHandler = new CComObject<CMyEventHandler>;

                /* Get the connection point */
                CComQIPtr<IConnectionPointContainer, &__uuidof(IConnectionPointContainer)> spConnectionContainer( spWMPPlayer );
                if( spConnectionContainer )
                {
                hr = spConnectionContainer->FindConnectionPoint( __uuidof(IWMPEvents), &spConnectionPoint )
                if( pMyEventHandler && SU

                D Offline
                D Offline
                David Crow
                wrote on last edited by
                #11

                Roger Stoltz wrote:

                I hope you'll find the above helpful.

                Yes, the compiler is happy now. It's still a tad confusing, however, since the two examples I was using as a reference were calling CreateInstance(). Upon running the code, Advise() is returning 0x80040202 (CONNECT_E_CANNOTCONNECT). MSDN article Q183216 talks about my sink object (CMyEventHandler) may be missing something that QueryInterface() is looking for. As far as I can tell, my sink object has implemented all of the IWMPEvents methods.

                "One man's wage rise is another man's price increase." - Harold Wilson

                "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                "Man who follows car will be exhausted." - Confucius

                R 1 Reply Last reply
                0
                • D David Crow

                  Roger Stoltz wrote:

                  I hope you'll find the above helpful.

                  Yes, the compiler is happy now. It's still a tad confusing, however, since the two examples I was using as a reference were calling CreateInstance(). Upon running the code, Advise() is returning 0x80040202 (CONNECT_E_CANNOTCONNECT). MSDN article Q183216 talks about my sink object (CMyEventHandler) may be missing something that QueryInterface() is looking for. As far as I can tell, my sink object has implemented all of the IWMPEvents methods.

                  "One man's wage rise is another man's price increase." - Harold Wilson

                  "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                  "Man who follows car will be exhausted." - Confucius

                  R Offline
                  R Offline
                  Roger Stoltz
                  wrote on last edited by
                  #12

                  DavidCrow wrote:

                  MSDN article Q183216 talks about my sink object (CMyEventHandler) may be missing something that QueryInterface() is looking for. As far as I can tell, my sink object has implemented all of the IWMPEvents methods.

                  The article Q183216 is talking about when the server is querying for the source interface, IWMPEvents in your case, and the client who is supposed to implement the interface responds with an error that says the interface is not supported/implemented. The error returned to the server is most likely E_NOINTERFACE. For this to be applicable in your situation you must have forgotten to put the entry in the COM_MAP, but as I understand from your previous posts you've already got that in place. This made me wonder if the server might be requesting another interface such as IDispatch, e.g. if the IWMPEvents inherits from IDispatch, but as far as I can tell with the OLEView tool this is not the case. Can you successfully "find" the connection point with IConnectionPointContainer::FindConnectionPoint()? Are you possibly making the call from a worker thread? If you are, does it work if you try to do this from your main thread?

                  "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                  "High speed never compensates for wrong direction!" - unknown

                  D 1 Reply Last reply
                  0
                  • R Roger Stoltz

                    DavidCrow wrote:

                    MSDN article Q183216 talks about my sink object (CMyEventHandler) may be missing something that QueryInterface() is looking for. As far as I can tell, my sink object has implemented all of the IWMPEvents methods.

                    The article Q183216 is talking about when the server is querying for the source interface, IWMPEvents in your case, and the client who is supposed to implement the interface responds with an error that says the interface is not supported/implemented. The error returned to the server is most likely E_NOINTERFACE. For this to be applicable in your situation you must have forgotten to put the entry in the COM_MAP, but as I understand from your previous posts you've already got that in place. This made me wonder if the server might be requesting another interface such as IDispatch, e.g. if the IWMPEvents inherits from IDispatch, but as far as I can tell with the OLEView tool this is not the case. Can you successfully "find" the connection point with IConnectionPointContainer::FindConnectionPoint()? Are you possibly making the call from a worker thread? If you are, does it work if you try to do this from your main thread?

                    "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                    "High speed never compensates for wrong direction!" - unknown

                    D Offline
                    D Offline
                    David Crow
                    wrote on last edited by
                    #13

                    Roger Stoltz wrote:

                    The error returned to the server is most likely E_NOINTERFACE.

                    Which is 0x8004002. The error that I am getting is 0x80040202.

                    Roger Stoltz wrote:

                    For this to be applicable in your situation you must have forgotten to put the entry in the COM_MAP, but as I understand from your previous posts you've already got that in place. This made me wonder if the server might be requesting another interface such as IDispatch, e.g. if the IWMPEvents inherits from IDispatch, but as far as I can tell with the OLEView tool this is not the case.

                    class ATL_NO_VTABLE CMyEventHandler :
                    public CComObjectRootEx,
                    public CComCoClass,
                    public IDispatchImpl,
                    public IWMPEvents
                    {
                    public:
                    CMyEventHandler() {}

                    DECLARE_REGISTRY_RESOURCEID(IDR_MYEVENTHANDLER)

                    DECLARE_PROTECT_FINAL_CONSTRUCT()

                    BEGIN_COM_MAP(CMyEventHandler)
                    COM_INTERFACE_ENTRY(IMyEventHandler)
                    COM_INTERFACE_ENTRY(IDispatch)
                    COM_INTERFACE_ENTRY(IWMPEvents)
                    END_COM_MAP()

                    ...
                    };

                    Roger Stoltz wrote:

                    Can you successfully "find" the connection point with IConnectionPointContainer::FindConnectionPoint()?

                    QueryInterface() and FindConnectionPoint() both return S_OK.

                    Roger Stoltz wrote:

                    Are you possibly making the call from a worker thread? If you are, does it work if you try to do this from your main thread?

                    No additional threads have been created. My call to Advise() differs from yours in how I had to cast the first argument:

                    hr = connectionPoint->Advise((IWMPEvents *) pEventHandler, &dwAdviseCookie);

                    Casting it to IUnknown* yielded: error C2594: 'type cast' : ambiguous conversions from 'class CMyEventHandler *' to 'struct IUnknown *'

                    "One man's wage rise is another man's price increase." - Harold Wilson

                    "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                    "Man who follows car will be exhausted." - Confucius

                    R 1 Reply Last reply
                    0
                    • D David Crow

                      Roger Stoltz wrote:

                      The error returned to the server is most likely E_NOINTERFACE.

                      Which is 0x8004002. The error that I am getting is 0x80040202.

                      Roger Stoltz wrote:

                      For this to be applicable in your situation you must have forgotten to put the entry in the COM_MAP, but as I understand from your previous posts you've already got that in place. This made me wonder if the server might be requesting another interface such as IDispatch, e.g. if the IWMPEvents inherits from IDispatch, but as far as I can tell with the OLEView tool this is not the case.

                      class ATL_NO_VTABLE CMyEventHandler :
                      public CComObjectRootEx,
                      public CComCoClass,
                      public IDispatchImpl,
                      public IWMPEvents
                      {
                      public:
                      CMyEventHandler() {}

                      DECLARE_REGISTRY_RESOURCEID(IDR_MYEVENTHANDLER)

                      DECLARE_PROTECT_FINAL_CONSTRUCT()

                      BEGIN_COM_MAP(CMyEventHandler)
                      COM_INTERFACE_ENTRY(IMyEventHandler)
                      COM_INTERFACE_ENTRY(IDispatch)
                      COM_INTERFACE_ENTRY(IWMPEvents)
                      END_COM_MAP()

                      ...
                      };

                      Roger Stoltz wrote:

                      Can you successfully "find" the connection point with IConnectionPointContainer::FindConnectionPoint()?

                      QueryInterface() and FindConnectionPoint() both return S_OK.

                      Roger Stoltz wrote:

                      Are you possibly making the call from a worker thread? If you are, does it work if you try to do this from your main thread?

                      No additional threads have been created. My call to Advise() differs from yours in how I had to cast the first argument:

                      hr = connectionPoint->Advise((IWMPEvents *) pEventHandler, &dwAdviseCookie);

                      Casting it to IUnknown* yielded: error C2594: 'type cast' : ambiguous conversions from 'class CMyEventHandler *' to 'struct IUnknown *'

                      "One man's wage rise is another man's price increase." - Harold Wilson

                      "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                      "Man who follows car will be exhausted." - Confucius

                      R Offline
                      R Offline
                      Roger Stoltz
                      wrote on last edited by
                      #14

                      DavidCrow wrote:

                      Roger Stoltz wrote:

                      The error returned to the server is most likely E_NOINTERFACE.

                      Which is 0x8004002. The error that I am getting is 0x80040202.

                      Well, you're not the server which means that what I'm talking about is the error message your client is sending the Media Player when the Media Player server asks for your implementation of the IWMPEvents source interface. David, now I'm just guessing, but I get the impression that you've misinterpreted some part of what I've been trying to explain and I cannot really figure out what part... Most likely I haven't been very clear on the subject so let me try again. It looks like you've opted for my suggestion based on a nested class to use as an event sink, otherwise I don't understand your pEventHandler variable as it should be this in the call to Advise(). Whatever pEventHandler points to doesn't seem to expose the IWMPEvents interface judging from the error you got. If you are using the nested class version you should remove the IWMPEvents entry from the COM_MAP in the outer class and put it into the presumably non-existing COM_MAP of the inner/nested class. You can think of the COM_MAP as being traversed when QueryInterface() is called on your object. I don't understand why you're exposing the IMyEventHandler and IDispatch interfaces from your class. Perhaps you did it intentionally or it could be a misunderstanding. Who is going to use those interfaces? If you're not trying to develop a COM server yourself that exposes e.g. IMyEventHandler, then I guess it shouldn't be there in the first place. However, now that you've provided an important part of your class declaration I can try and patch together a declaration based on the nested class scenario for you. I hope things will clear up afterwards. It should look something like this:

                      class ATL_NO_VTABLE CMyEventHandler :
                      public CComObjectRootEx<CComSingleThreadModel>,
                      public CComCoClass<CMyEventHandler, &CLSID_MyEventHandler>,
                      public IDispatchImpl,
                      {
                      public:
                      CMyEventHandler() {}

                      DECLARE_REGISTRY_RESOURCEID(IDR_MYEVENTHANDLER)

                      DECLARE_PROTECT_FINAL_CONSTRUCT()

                      BEGIN_COM_MAP(CMyEventHandler)
                      COM_INTERFACE_ENTRY(IMyEventHandler)
                      COM_INTERFACE_ENTRY(IDispatch)
                      END_

                      D 1 Reply Last reply
                      0
                      • R Roger Stoltz

                        DavidCrow wrote:

                        Roger Stoltz wrote:

                        The error returned to the server is most likely E_NOINTERFACE.

                        Which is 0x8004002. The error that I am getting is 0x80040202.

                        Well, you're not the server which means that what I'm talking about is the error message your client is sending the Media Player when the Media Player server asks for your implementation of the IWMPEvents source interface. David, now I'm just guessing, but I get the impression that you've misinterpreted some part of what I've been trying to explain and I cannot really figure out what part... Most likely I haven't been very clear on the subject so let me try again. It looks like you've opted for my suggestion based on a nested class to use as an event sink, otherwise I don't understand your pEventHandler variable as it should be this in the call to Advise(). Whatever pEventHandler points to doesn't seem to expose the IWMPEvents interface judging from the error you got. If you are using the nested class version you should remove the IWMPEvents entry from the COM_MAP in the outer class and put it into the presumably non-existing COM_MAP of the inner/nested class. You can think of the COM_MAP as being traversed when QueryInterface() is called on your object. I don't understand why you're exposing the IMyEventHandler and IDispatch interfaces from your class. Perhaps you did it intentionally or it could be a misunderstanding. Who is going to use those interfaces? If you're not trying to develop a COM server yourself that exposes e.g. IMyEventHandler, then I guess it shouldn't be there in the first place. However, now that you've provided an important part of your class declaration I can try and patch together a declaration based on the nested class scenario for you. I hope things will clear up afterwards. It should look something like this:

                        class ATL_NO_VTABLE CMyEventHandler :
                        public CComObjectRootEx<CComSingleThreadModel>,
                        public CComCoClass<CMyEventHandler, &CLSID_MyEventHandler>,
                        public IDispatchImpl,
                        {
                        public:
                        CMyEventHandler() {}

                        DECLARE_REGISTRY_RESOURCEID(IDR_MYEVENTHANDLER)

                        DECLARE_PROTECT_FINAL_CONSTRUCT()

                        BEGIN_COM_MAP(CMyEventHandler)
                        COM_INTERFACE_ENTRY(IMyEventHandler)
                        COM_INTERFACE_ENTRY(IDispatch)
                        END_

                        D Offline
                        D Offline
                        David Crow
                        wrote on last edited by
                        #15

                        Thanks for the help, Roger. I'll eventually get my head wrapped around this.

                        Roger Stoltz wrote:

                        Well, you're not the server which means that what I'm talking about is the error message your client is sending the Media Player when the Media Player server asks for your implementation of the IWMPEvents source interface.

                        I was probably confusing who was the client and who was the server. I'm not intentionally trying to create a server, but rather use the Media Player server.

                        Roger Stoltz wrote:

                        Whatever pEventHandler points to doesn't seem to expose the IWMPEvents interface judging from the error you got.

                        Previously, my CMyEventHandler class was derived from, among others, IWMPEvents, and I thought I had the appropriate IWMPEvents entry in the BEGIN_COM_MAP() macro. So I don't understand what the Media Player server could have been asking for that I was not providing/exposing.

                        Roger Stoltz wrote:

                        I don't understand why you're exposing the IMyEventHandler and IDispatch interfaces from your class. Perhaps you did it intentionally or it could be a misunderstanding. Who is going to use those interfaces? If you're not trying to develop a COM server yourself that exposes e.g. IMyEventHandler, then I guess it shouldn't be there in the first place.

                        They were added by the ATL Object Wizard. How does moving the IWMPEvents interface to CMyEventSink differ from having it in CMyEventHandler?

                        "One man's wage rise is another man's price increase." - Harold Wilson

                        "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                        "Man who follows car will be exhausted." - Confucius

                        R 1 Reply Last reply
                        0
                        • D David Crow

                          Thanks for the help, Roger. I'll eventually get my head wrapped around this.

                          Roger Stoltz wrote:

                          Well, you're not the server which means that what I'm talking about is the error message your client is sending the Media Player when the Media Player server asks for your implementation of the IWMPEvents source interface.

                          I was probably confusing who was the client and who was the server. I'm not intentionally trying to create a server, but rather use the Media Player server.

                          Roger Stoltz wrote:

                          Whatever pEventHandler points to doesn't seem to expose the IWMPEvents interface judging from the error you got.

                          Previously, my CMyEventHandler class was derived from, among others, IWMPEvents, and I thought I had the appropriate IWMPEvents entry in the BEGIN_COM_MAP() macro. So I don't understand what the Media Player server could have been asking for that I was not providing/exposing.

                          Roger Stoltz wrote:

                          I don't understand why you're exposing the IMyEventHandler and IDispatch interfaces from your class. Perhaps you did it intentionally or it could be a misunderstanding. Who is going to use those interfaces? If you're not trying to develop a COM server yourself that exposes e.g. IMyEventHandler, then I guess it shouldn't be there in the first place.

                          They were added by the ATL Object Wizard. How does moving the IWMPEvents interface to CMyEventSink differ from having it in CMyEventHandler?

                          "One man's wage rise is another man's price increase." - Harold Wilson

                          "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                          "Man who follows car will be exhausted." - Confucius

                          R Offline
                          R Offline
                          Roger Stoltz
                          wrote on last edited by
                          #16

                          DavidCrow wrote:

                          Previously, my CMyEventHandler class was derived from, among others, IWMPEvents, and I thought I had the appropriate IWMPEvents entry in the BEGIN_COM_MAP() macro. So I don't understand what the Media Player server could have been asking for that I was not providing/exposing.

                          Yep, but as I understand it you got a compiler error at that time and not the runtime error that says the server cannot find the IWMPEvents interface in your client.

                          DavidCrow wrote:

                          They were added by the ATL Object Wizard.

                          Okay. You probably used the wizard that is used for creating COM servers. But that's a minor problem, it just made me unsure of what you were trying to do. Never mind.

                          DavidCrow wrote:

                          How does moving the IWMPEvents interface to CMyEventSink differ from having it in CMyEventHandler?

                          In your case it doesn't really make a difference in practice. However, I consider the nested class a more versatile solution or design pattern. One major benefit is to avoid circular references. Consider COM server A that creates another COM server B. A is created by the client C. B exposes a source interface, e.g. a connection point, for which A implements an event sink and register itself for receiving COM events from B. When B requests the interface for the event sink it will increment the reference of A according to COM rules. The problem is that when C wants to destroy A by releasing its last reference, the A reference counter will not reach zero as B still holds a reference to it. This will force a kind of catch 22 situation where neither A nor B will get their last reference released. The root cause is that both C and B uses the same object for reference counting in A. One solution is to create another object, like a nested class inside A, that serves as event sink. My point is that if you master this way of creating an event sink, you'll probably never have to do it in another way. I also consider it more clean from a design point of view.

                          "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                          "High speed never compensates for wrong direction!" - unknown

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups