none
SendMessageA "access violation"

    Question

  •  

    Hi, I'm trying to send a string from one dll to another application's window using SendMessage and WM_COPYDATA (as described here: http://www.codeproject.com/threads/ipc_wmcopy.asp).

     

    I get the window handle of my target window fine, but when I send the message I get an access violation reading from the pointer CD.lpData (points to the string I'm trying to send).

     

    What's strange is that the function works great if I change the input parameter of the function from CString to WCHAR (although the string contents are completely hosed).

     

    I'm confused because I'm using the exact code as provided in the example... can you tell me what's wrong?

     

    (I get the AV on SendMessageA line, reading location 0xfeeefeee which is whats stored in CD.lpData.)

     

    Here is the sending function:

     

    Code Snippet

    int __declspec(dllexport) sendAnvil(CString s) {

    LRESULT worked = 0;

    HWND hdlAnVig = NULL;

    // get window handle of our window

    hdlAnVig = FindWindowA(NULL,"AnVignal");

     

    if (hdlAnVig) {

     

    COPYDATASTRUCT CD;

    CD.dwData=0;

    CD.cbData = s.GetLength();

    CD.lpData= (void*)s.GetBuffer(CD.cbData);

    worked = SendMessageA(hdlAnVig,WM_COPYDATA,0,(LPARAM)&CD);

    }

    s.ReleaseBuffer(-1);

    }

    return (int)worked;

    }

     

    Tuesday, May 01, 2007 3:10 PM

Answers

  •  

    that did help... actually I figured this out.  My sending DLL needed to receive the string as an LPCTSTR from the originating application in order for it to be valid (rather than as a CString).  Similiar to your suggestion I also needed to get strength length from somewhere else, because .getlength doesn't seem to return the length of the string itself (for some reason). 

     

    I was still getting an access violation, although I could AfxMessageBox my pointer on sending side so I knew the pointer was valid... so I switched the FindWindow calls back to non-object (function versus creating CWhd and doing CWhd->FindWindow... calling getSafeHndWnd in the SendMessage line was giving the access violation... when I switched back to standard FindWindowA call everything worked.  here's the code.

     

    SENDER

    -------------

     

    int __declspec(dllexport) sendAnvil(LPCTSTR s) {
     LRESULT worked = 0;
     
     // get window handle of our anvignal window
     HWND hdlAnVig = FindWindowA(NULL,"AnVignal");
     
     if (hdlAnVig) {
       COPYDATASTRUCT CD;  // windows-provided structure for this purpose

      CD.dwData=1; // 1=place an order
      
      int len = 0;
      len = strlen(s);
      CD.cbData = len+1;
      CD.lpData = (void*)s;
      
      worked = SendMessageA(hdlAnVig,WM_COPYDATA,0,(LPARAM)&CD);
      } else {
      AfxMessageBox((LPCTSTR)"Unable to find AnVignal.  Please verify Anvil is running and AnVignal.dll extension is loaded.");
     }
     return (int)worked;

     

    RECEIVER

    -------------------

     

    BOOL ExtFrame:SurprisenCopyData(CWnd* sWnd, COPYDATASTRUCT* CD)
    {
     TRACE0("got COPYDATA");
     CString gotMsg = (LPCTSTR)(CD->lpData);
     int gotType = (int)(CD->dwData);

     switch (gotType) {
      case 1 :  
       TRACE0("got right type");
       return AvSendorder(gotMsg);// send an order
       break;
      default :
       TRACE0("got unrecognized type");
       break;
     }
     return false;
     // this line was in my included example but incorrect
     // return ExtFrame:SurprisenCopyData(sWnd, CD);
    }

    Friday, May 04, 2007 3:49 PM

All replies

  • What code are you using to read it at the other end?
    Tuesday, May 01, 2007 3:39 PM
  •  

    visual c++ on both sides.  it's also a DLL on both sides, which is the only difference I can find between my app and the example app I referenced (which runs fine on my machine).

     

    it's not even getting to the other side though at the moment.  However if I change the sending string from CString to WCHAR (and cast it immediately back to CString), the text is sent and executes in the other application... but the content is completely hosed.

     

    so I'm not sure whats going on...

    Tuesday, May 01, 2007 3:46 PM
  •  

    just occured that you might actually want to see the code on either side Smile

     

    in the header file we've got:

     

    afx_msg BOOL OnCopyData(CWnd* sWnd,COPYDATASTRUCT* pCD);

     

    in the message map we've got:

    ON_WM_COPYDATA()

     

    then finally the handler: 

    Code Snippet

     

    BOOL ExtFrame::OnCopyData(CWnd* sWnd, COPYDATASTRUCT* CD)

    {

    TRACE0("got COPYDATA");

    CString gotMsg = (LPCSTR)(CD->lpData);

    int gotType = (int)(CD->dwData);

    switch (gotType) {

    case 0 :

    TRACE0("got right type");

    AvSendorder(gotMsg);// send an order

    return true;

    break;

    default :

    TRACE0("got unrecognized type");

    AfxMessageBox("WM_COPYDATA message was not a recognized type.");

    break;

    }

    return ExtFrame::OnCopyData(sWnd, CD);

    }

     

    Tuesday, May 01, 2007 4:11 PM
  •  

    here I see that the value that the COPYDATASTRUCT pointer points to is a standard initialization value for memory allocated from heap, although this doesn't appear to tell me much to help my problem.

     

    ----------------------------

     

    Microsoft's memory management functions often initialize memory with special values. The following article describes frequent used variants.

    Windows NT memory codes


    0xFEEEFEEE - OS fill heap memory, which was marked for usage, but wasn't allocated by HeapAlloc() or LocalAlloc(). Or that memory just has been freed by HeapFree().

    -----------------------

    from

    http://www.docsultant.com/site2/articles%5Cdebug_codes.html

    Tuesday, May 01, 2007 6:04 PM
  • I would suggest the following attempt:

    Code Snippet

    // sender:

    CD.cbData = (s.GetLength() + 1) * sizeof(s[0]);

    CD.lpData= (LPVOID)(LPCTSTR)s;

     

    // receiver:

    CString gotMsg = (LPCTSTR)CD->lpData;

     

    The above is for the cases both of sender and receiver have the same Unicode or non-Unicode compiler configuration. From your code it seems the sender is Unicode and receiver is non-Unicode. In this case the receiver should do:

     

    Code Snippet

    // receiver:

    CString gotMsg((LPCWSTR)CD->lpData);

     

    However I think it is better to use the same string type in both projects.

     

    I hope this helps.

    Wednesday, May 02, 2007 8:47 AM
  •  

    that did help... actually I figured this out.  My sending DLL needed to receive the string as an LPCTSTR from the originating application in order for it to be valid (rather than as a CString).  Similiar to your suggestion I also needed to get strength length from somewhere else, because .getlength doesn't seem to return the length of the string itself (for some reason). 

     

    I was still getting an access violation, although I could AfxMessageBox my pointer on sending side so I knew the pointer was valid... so I switched the FindWindow calls back to non-object (function versus creating CWhd and doing CWhd->FindWindow... calling getSafeHndWnd in the SendMessage line was giving the access violation... when I switched back to standard FindWindowA call everything worked.  here's the code.

     

    SENDER

    -------------

     

    int __declspec(dllexport) sendAnvil(LPCTSTR s) {
     LRESULT worked = 0;
     
     // get window handle of our anvignal window
     HWND hdlAnVig = FindWindowA(NULL,"AnVignal");
     
     if (hdlAnVig) {
       COPYDATASTRUCT CD;  // windows-provided structure for this purpose

      CD.dwData=1; // 1=place an order
      
      int len = 0;
      len = strlen(s);
      CD.cbData = len+1;
      CD.lpData = (void*)s;
      
      worked = SendMessageA(hdlAnVig,WM_COPYDATA,0,(LPARAM)&CD);
      } else {
      AfxMessageBox((LPCTSTR)"Unable to find AnVignal.  Please verify Anvil is running and AnVignal.dll extension is loaded.");
     }
     return (int)worked;

     

    RECEIVER

    -------------------

     

    BOOL ExtFrame:SurprisenCopyData(CWnd* sWnd, COPYDATASTRUCT* CD)
    {
     TRACE0("got COPYDATA");
     CString gotMsg = (LPCTSTR)(CD->lpData);
     int gotType = (int)(CD->dwData);

     switch (gotType) {
      case 1 :  
       TRACE0("got right type");
       return AvSendorder(gotMsg);// send an order
       break;
      default :
       TRACE0("got unrecognized type");
       break;
     }
     return false;
     // this line was in my included example but incorrect
     // return ExtFrame:SurprisenCopyData(sWnd, CD);
    }

    Friday, May 04, 2007 3:49 PM