Hooks, delegates and callbacks

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris Tacke, eMVP

    #1

    Hooks, delegates and callbacks

    I'm not sure whether this is a C# or C++ question, so I'm asking in both
    groups.

    Here's my scenario:
    I need to get all text added to a ListBox that is in another process that I
    have no control over. I want to get this information in my C# application
    through a callback.

    Here's what I've done:
    Since global hooks must be done in C, I've written a simple DLL that finds
    the handle of the ListBox I want the info from, hooks it, and gets the
    string data as it is added. This all works just fine.

    The problem:
    From C# I create a delegate and pass it into the DLL prior to hooking the
    ListBox. The DLL then saves the function pointer to a global variable for
    use in the hook procedure. I *can* successfully call the callback from the
    routine that accepts the handler. When I try to use said handle from the
    hook proc, it is NULL and things go bad.

    So this is basically what I've got:

    #pragma data_seg(".shar ed")
    CallBack m_callback = NULL;
    #pragma data_seg()

    typedef void (__stdcall *CallBack)(LPCT STR);

    __declspec(dlle xport)
    BOOL __stdcall LoadHook(CallBa ck callback)
    {
    // If already hooked, don't do it again.

    // save the hook to a global area
    m_callback = callback;

    // I *CAN* call the callback here - this works:
    m_callback("tes t");
    }

    LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
    {
    CWPSTRUCT *lpcwt;
    lpcwt = (CWPSTRUCT *)lParam;

    switch (lpcwt->message)
    {

    case LB_ADDSTRING:
    // my global callback handle is ALWAYS NULL here
    if(m_callback)
    m_callback("tes t");

    }
    }


    I've also tried using a memory-mapped file to store the callback function
    pointer, but that also fails.

    Is there something special about a hook proc that makes this so it can't
    work?

    Any pointers are GREATLY appreciated!

    --
    Chris Tacke, eMVP
    Advisory Board Member
    Find information, resources and relevant links for opennetcf.org. This domain may be for sale.

    ---
    Windows CE Product Manager
    Applied Data Systems



  • Grant Richins [MS]

    #2
    Re: Hooks, delegates and callbacks

    Are you sure you're keeping a reference to the delegate in your C# code?
    Otherwise the GC will think the delegate is available for collection.

    --
    --Grant
    This posting is provided "AS IS" with no warranties, and confers no rights.


    Comment

    • Chris Tacke, eMVP

      #3
      Re: Hooks, delegates and callbacks

      It's a member variable of the C# calling class, which is a member variable
      of my main app Form, so it should be valid until the form dies. Is it
      possible that it's getting moved by the memory manager or something? Here
      are the C# guts....

      public delegate void HookCallback(st ring Message);

      public class DataGrabber : System.Windows. Forms.Form
      {
      private HookClass m_hook;

      ....
      }

      public class HookClass
      {
      private HookCallback hookcallback;

      public HookClass()
      {
      hookcallback = new HookCallback(Ho okProc);

      LoadHook(hookca llback);
      }

      public void HookProc(string Message)
      {
      }

      [DllImport("MyHo ok.dll", CallingConventi on=CallingConve ntion.StdCall)]
      internal static extern int LoadHook(HookCa llback cb);
      }




      --
      Chris Tacke, eMVP
      Advisory Board Member
      Find information, resources and relevant links for opennetcf.org. This domain may be for sale.

      ---
      Windows CE Product Manager
      Applied Data Systems


      "Grant Richins [MS]" <grantri@online .microsoft.com> wrote in message
      news:%2362LEcdi DHA.2400@TK2MSF TNGP11.phx.gbl. ..[color=blue]
      > Are you sure you're keeping a reference to the delegate in your C# code?
      > Otherwise the GC will think the delegate is available for collection.
      >
      > --
      > --Grant
      > This posting is provided "AS IS" with no warranties, and confers no[/color]
      rights.[color=blue]
      >
      >[/color]


      Comment

      • Mattias Sjögren

        #4
        Re: Hooks, delegates and callbacks

        Chris,
        [color=blue]
        >Here's my scenario:
        >I need to get all text added to a ListBox that is in another process that I
        >have no control over. I want to get this information in my C# application
        >through a callback.[/color]

        Do you have to get new strings when they are added to the listbox? I
        think it would be easier to do a polling solution that checks for
        changes in the listbox at a fixed interval.

        [color=blue]
        >The problem:
        >From C# I create a delegate and pass it into the DLL prior to hooking the
        >ListBox.[/color]

        That won't work since the callback address is only valid in the
        process space of your app, not the hooked app.

        You have to find another way to pass back the information to the C#
        app. Perhaps sending a WM_COPYDATA message or putting the data in a
        memory mapped file.



        Mattias

        --
        Mattias Sjögren [MVP] mattias @ mvps.org

        Please reply only to the newsgroup.

        Comment

        • 100

          #5
          Re: Hooks, delegates and callbacks

          Hi Chris,
          Do you use /SECTION I can't seet in your code. Without that you don't share
          anything

          #pragma comment(linker, "/SECTION:.shared ,RWS")
          #pragma data_seg(".shar ed")
          int nShared = 0;
          #pragma data_seg()

          HTH
          B\rgds
          100

          "Chris Tacke, eMVP" <ctacke@spamfre e-opennetcf.org> wrote in message
          news:%23Kqxt8bi DHA.1692@TK2MSF TNGP10.phx.gbl. ..[color=blue]
          > I'm not sure whether this is a C# or C++ question, so I'm asking in both
          > groups.
          >
          > Here's my scenario:
          > I need to get all text added to a ListBox that is in another process that[/color]
          I[color=blue]
          > have no control over. I want to get this information in my C# application
          > through a callback.
          >
          > Here's what I've done:
          > Since global hooks must be done in C, I've written a simple DLL that finds
          > the handle of the ListBox I want the info from, hooks it, and gets the
          > string data as it is added. This all works just fine.
          >
          > The problem:
          > From C# I create a delegate and pass it into the DLL prior to hooking the
          > ListBox. The DLL then saves the function pointer to a global variable for
          > use in the hook procedure. I *can* successfully call the callback from[/color]
          the[color=blue]
          > routine that accepts the handler. When I try to use said handle from the
          > hook proc, it is NULL and things go bad.
          >
          > So this is basically what I've got:
          >
          > #pragma data_seg(".shar ed")
          > CallBack m_callback = NULL;
          > #pragma data_seg()
          >
          > typedef void (__stdcall *CallBack)(LPCT STR);
          >
          > __declspec(dlle xport)
          > BOOL __stdcall LoadHook(CallBa ck callback)
          > {
          > // If already hooked, don't do it again.
          >
          > // save the hook to a global area
          > m_callback = callback;
          >
          > // I *CAN* call the callback here - this works:
          > m_callback("tes t");
          > }
          >
          > LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
          > {
          > CWPSTRUCT *lpcwt;
          > lpcwt = (CWPSTRUCT *)lParam;
          >
          > switch (lpcwt->message)
          > {
          >
          > case LB_ADDSTRING:
          > // my global callback handle is ALWAYS NULL here
          > if(m_callback)
          > m_callback("tes t");
          >
          > }
          > }
          >
          >
          > I've also tried using a memory-mapped file to store the callback function
          > pointer, but that also fails.
          >
          > Is there something special about a hook proc that makes this so it can't
          > work?
          >
          > Any pointers are GREATLY appreciated!
          >
          > --
          > Chris Tacke, eMVP
          > Advisory Board Member
          > www.OpenNETCF.org
          > ---
          > Windows CE Product Manager
          > Applied Data Systems
          > www.applieddata.net
          >
          >[/color]


          Comment

          • Chris Tacke, eMVP

            #6
            Re: Hooks, delegates and callbacks

            Yep, it's time dependent and actually must link with another thread
            gathering other data at the same time, so polling won't work.

            --
            Chris Tacke, eMVP
            Advisory Board Member
            Find information, resources and relevant links for opennetcf.org. This domain may be for sale.

            ---
            Windows CE Product Manager
            Applied Data Systems


            "Mattias Sjögren" <mattias.dont.w ant.spam@mvps.o rg> wrote in message
            news:u4u9J5eiDH A.604@TK2MSFTNG P10.phx.gbl...[color=blue]
            > Chris,
            >[color=green]
            > >Here's my scenario:
            > >I need to get all text added to a ListBox that is in another process that[/color][/color]
            I[color=blue][color=green]
            > >have no control over. I want to get this information in my C#[/color][/color]
            application[color=blue][color=green]
            > >through a callback.[/color]
            >
            > Do you have to get new strings when they are added to the listbox? I
            > think it would be easier to do a polling solution that checks for
            > changes in the listbox at a fixed interval.
            >
            >[color=green]
            > >The problem:
            > >From C# I create a delegate and pass it into the DLL prior to hooking the
            > >ListBox.[/color]
            >
            > That won't work since the callback address is only valid in the
            > process space of your app, not the hooked app.
            >
            > You have to find another way to pass back the information to the C#
            > app. Perhaps sending a WM_COPYDATA message or putting the data in a
            > memory mapped file.
            >
            >
            >
            > Mattias
            >
            > --
            > Mattias Sjögren [MVP] mattias @ mvps.org
            > http://www.msjogren.net/dotnet/
            > Please reply only to the newsgroup.[/color]


            Comment

            • Chris Tacke, eMVP

              #7
              Re: Hooks, delegates and callbacks

              the #pragma comment line just adds a linker option without me having to go
              to the project settings. The shared segment name is ".shared"

              --
              Chris Tacke, eMVP
              Advisory Board Member
              Find information, resources and relevant links for opennetcf.org. This domain may be for sale.

              ---
              Windows CE Product Manager
              Applied Data Systems


              "100" <100@100.com> wrote in message
              news:%23rURuMfi DHA.1172@TK2MSF TNGP09.phx.gbl. ..[color=blue]
              > Hi Chris,
              > Do you use /SECTION I can't seet in your code. Without that you don't[/color]
              share[color=blue]
              > anything
              >
              > #pragma comment(linker, "/SECTION:.shared ,RWS")
              > #pragma data_seg(".shar ed")
              > int nShared = 0;
              > #pragma data_seg()
              >
              > HTH
              > B\rgds
              > 100
              >
              > "Chris Tacke, eMVP" <ctacke@spamfre e-opennetcf.org> wrote in message
              > news:%23Kqxt8bi DHA.1692@TK2MSF TNGP10.phx.gbl. ..[color=green]
              > > I'm not sure whether this is a C# or C++ question, so I'm asking in both
              > > groups.
              > >
              > > Here's my scenario:
              > > I need to get all text added to a ListBox that is in another process[/color][/color]
              that[color=blue]
              > I[color=green]
              > > have no control over. I want to get this information in my C#[/color][/color]
              application[color=blue][color=green]
              > > through a callback.
              > >
              > > Here's what I've done:
              > > Since global hooks must be done in C, I've written a simple DLL that[/color][/color]
              finds[color=blue][color=green]
              > > the handle of the ListBox I want the info from, hooks it, and gets the
              > > string data as it is added. This all works just fine.
              > >
              > > The problem:
              > > From C# I create a delegate and pass it into the DLL prior to hooking[/color][/color]
              the[color=blue][color=green]
              > > ListBox. The DLL then saves the function pointer to a global variable[/color][/color]
              for[color=blue][color=green]
              > > use in the hook procedure. I *can* successfully call the callback from[/color]
              > the[color=green]
              > > routine that accepts the handler. When I try to use said handle from[/color][/color]
              the[color=blue][color=green]
              > > hook proc, it is NULL and things go bad.
              > >
              > > So this is basically what I've got:
              > >
              > > #pragma data_seg(".shar ed")
              > > CallBack m_callback = NULL;
              > > #pragma data_seg()
              > >
              > > typedef void (__stdcall *CallBack)(LPCT STR);
              > >
              > > __declspec(dlle xport)
              > > BOOL __stdcall LoadHook(CallBa ck callback)
              > > {
              > > // If already hooked, don't do it again.
              > >
              > > // save the hook to a global area
              > > m_callback = callback;
              > >
              > > // I *CAN* call the callback here - this works:
              > > m_callback("tes t");
              > > }
              > >
              > > LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam)
              > > {
              > > CWPSTRUCT *lpcwt;
              > > lpcwt = (CWPSTRUCT *)lParam;
              > >
              > > switch (lpcwt->message)
              > > {
              > >
              > > case LB_ADDSTRING:
              > > // my global callback handle is ALWAYS NULL here
              > > if(m_callback)
              > > m_callback("tes t");
              > >
              > > }
              > > }
              > >
              > >
              > > I've also tried using a memory-mapped file to store the callback[/color][/color]
              function[color=blue][color=green]
              > > pointer, but that also fails.
              > >
              > > Is there something special about a hook proc that makes this so it can't
              > > work?
              > >
              > > Any pointers are GREATLY appreciated!
              > >
              > > --
              > > Chris Tacke, eMVP
              > > Advisory Board Member
              > > www.OpenNETCF.org
              > > ---
              > > Windows CE Product Manager
              > > Applied Data Systems
              > > www.applieddata.net
              > >
              > >[/color]
              >
              >[/color]


              Comment

              • Grant Richins [MS]

                #8
                Re: Hooks, delegates and callbacks

                My only experience is using the function pointer while still inside the
                original function that got passed the delegate. My best guess is that once
                the function returns the runtime is tearing down the marshaled function
                pointer. I would try 2 things: pass the delegate in on a new thread, so it
                can block until the native function pointer is no longer needed, or try to
                figure out how to use Marshal.GetUnma nagedThunkForMa nagedMethodPtr.

                HTH

                --
                --Grant
                This posting is provided "AS IS" with no warranties, and confers no rights.


                Comment

                • Chris Tacke, eMVP

                  #9
                  Re: Hooks, delegates and callbacks

                  Godd ideas, thanks. Right now I'm chasing an alternate method of creating a
                  Window in my C# app, passing it's handle down to the DLL, which then uses
                  WM_COPYDATA to send the data back. Of course it's not working, but
                  hopefully it's something I've overlooked. I can cathc a WM_USER message,
                  but the lParam string is empty. When I move to WM_COPYDATA, I don't get the
                  message. Go figure.

                  --
                  Chris Tacke, eMVP
                  Advisory Board Member
                  Find information, resources and relevant links for opennetcf.org. This domain may be for sale.

                  ---
                  Windows CE Product Manager
                  Applied Data Systems


                  "Grant Richins [MS]" <grantri@online .microsoft.com> wrote in message
                  news:OF09c%23Cj DHA.2336@TK2MSF TNGP11.phx.gbl. ..[color=blue]
                  > My only experience is using the function pointer while still inside the
                  > original function that got passed the delegate. My best guess is that[/color]
                  once[color=blue]
                  > the function returns the runtime is tearing down the marshaled function
                  > pointer. I would try 2 things: pass the delegate in on a new thread, so[/color]
                  it[color=blue]
                  > can block until the native function pointer is no longer needed, or try to
                  > figure out how to use Marshal.GetUnma nagedThunkForMa nagedMethodPtr.
                  >
                  > HTH
                  >
                  > --
                  > --Grant
                  > This posting is provided "AS IS" with no warranties, and confers no[/color]
                  rights.[color=blue]
                  >
                  >[/color]


                  Comment

                  • Chris Tacke, eMVP

                    #10
                    Re: Hooks, delegates and callbacks

                    Well, I got the WM_COPYDATA piece working. I may go back and try to get the
                    callback working in the future, but the WM_COPYDATA showed an interesting
                    insight. If I pass in a target HWND for the WM_COPYDATA target and store it
                    in the shared data section it works just fine. It's just the callback
                    method pointer that gets destroyed. I'm thinking that you're right about
                    the marshaler tearing down the callback pointer.

                    --
                    Chris Tacke, eMVP
                    Advisory Board Member
                    Find information, resources and relevant links for opennetcf.org. This domain may be for sale.

                    ---
                    Windows CE Product Manager
                    Applied Data Systems


                    "Chris Tacke, eMVP" <ctacke@spamfre e-opennetcf.org> wrote in message
                    news:O2Z5shEjDH A.684@TK2MSFTNG P09.phx.gbl...[color=blue]
                    > Godd ideas, thanks. Right now I'm chasing an alternate method of creating[/color]
                    a[color=blue]
                    > Window in my C# app, passing it's handle down to the DLL, which then uses
                    > WM_COPYDATA to send the data back. Of course it's not working, but
                    > hopefully it's something I've overlooked. I can cathc a WM_USER message,
                    > but the lParam string is empty. When I move to WM_COPYDATA, I don't get[/color]
                    the[color=blue]
                    > message. Go figure.
                    >
                    > --
                    > Chris Tacke, eMVP
                    > Advisory Board Member
                    > www.OpenNETCF.org
                    > ---
                    > Windows CE Product Manager
                    > Applied Data Systems
                    > www.applieddata.net
                    >
                    > "Grant Richins [MS]" <grantri@online .microsoft.com> wrote in message
                    > news:OF09c%23Cj DHA.2336@TK2MSF TNGP11.phx.gbl. ..[color=green]
                    > > My only experience is using the function pointer while still inside the
                    > > original function that got passed the delegate. My best guess is that[/color]
                    > once[color=green]
                    > > the function returns the runtime is tearing down the marshaled function
                    > > pointer. I would try 2 things: pass the delegate in on a new thread, so[/color]
                    > it[color=green]
                    > > can block until the native function pointer is no longer needed, or try[/color][/color]
                    to[color=blue][color=green]
                    > > figure out how to use Marshal.GetUnma nagedThunkForMa nagedMethodPtr.
                    > >
                    > > HTH
                    > >
                    > > --
                    > > --Grant
                    > > This posting is provided "AS IS" with no warranties, and confers no[/color]
                    > rights.[color=green]
                    > >
                    > >[/color]
                    >
                    >[/color]


                    Comment

                    Working...