none
COM interop marshalling big buffer seems limit to 4kb RRS feed

  • Question

  • Hello,
    First I have to admit that I new to .net developpment.

    I develop a plugin for an application which expose COM object. I have to Implement a BlaBla object, defined as:

    Code Snippet

    // IDL definition

    struct RAWBUFFER
    {
       LONG width, height, scanline;
       [ref, size_is(height*scanline)] BYTE *buffer;
    };
    interface IBlaBla : IUnknown
    {
       HRESULT Rasterize([in, out] struct RAWBUFFER *pBuff);
       // 'size, height, scanline' are defined by the host application

       // 'buffer' is allocated by the host application and must be filled by me

    };


    The corresponding Interop code looks like:
    Code Snippet

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct RAWBUFFER
    {
       public int width;
       public int height;
       public int scanline;
       public IntPtr buffer;

       // cannot use MarshalAs UnmanagedType.LPArray because cannot specify     

       // buffer size with SizeParamIndex or SizeConst

    }

    public interface IBlaBla 

    {

       [PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
       int Rasterize([In, Out] ref RAWBUFFER pBuff);
    }


    Now my code, called with height=454, width=903, scanline=903, meaning an allocated buffer size of 409 962 byte.
    Code Snippet

    public int Rasterize(ref RAWBUFFER pBuff)
    {
       int idx = 0;
       try {
          for(; idx < pBuff.height * pBuff.width; idx++)
              Marshal.WriteByte(pBuff.buffer, idx, 0);

       } catch (Exception e) {

          // ...

       }

     which fail at idx=4184 with a System.AccessViolationException: "try to read or write a protected memory" (english translation)
    4184+3*sizeof(int) = 4196, so it seems to me that COM interop put this limit.
    Note that these stuff work nice when developped in native C++.
    I made some search on google, but find nothing concerning this behavior, so any idea?

    Thank's

    Friday, February 15, 2008 12:53 AM

All replies

  • The 400KB memory buffer is not marshalled in your case - there is no way .NET COM Interop could interfere, assuming the RAWBUFFER.buffer pointer value got copied correctly.

     

    So, there are two possible explanations:

    1. The method signature you provided in the IDL file does not match the actual method signature of the host application.

     

    2. The host application does not allocate the entire memory buffer, but instead relies on Structured Exception Handler to handle the Access Violation errors. Typically, such an application will commit the memory on-demand in its exception filter code and return EXCEPTION_CONTINUE_EXECUTION.

    A "plugin" written in unmanaged C++ will not see such Access Violation exceptions as long as it only uses C++ exception handling.

    However, the .NET Framework exposes every native exception as various Exception objects, in your case - AccessViolationException. Thus, the EXCEPTION_CONTINUE_EXECUTION trick is not supported while in managed code.

     

    <workaround section deleted - as it obviously will not help>

     

    --ab
    Sunday, February 17, 2008 1:08 AM
  • You have not show us how exactly the member-buffer of the RAWBUFFER was initialized. Could you please clarify?
    Monday, February 18, 2008 6:55 AM
  • from the API documentation of the host application:

      * The host application is responsible for allocating and liberating this memory buffer

      * pBuff is passed as [in, out] parameter because it contains an in-part, the organization of the memory (width, height, scanline), and an out-part, the buffer.

    Note that the IDL part said that the buffer really have a size of (height*scanline)

     

    From my code, I only try to set all buffer value to 0, for now.

    Doing a Marshal.ReadByte(pBuff.buffer, idx) show that the buffer has all it's data initialized to 0, but fail with the similar System.AccessViolationException at idx=4184

    note that this APi is currently used on unmanaged C++ without problem: I can fill the buffer with my color index, and the application correctly draw it.

    Monday, February 18, 2008 8:59 AM
  •  Andrey Burlak wrote:

    The 400KB memory buffer is not marshalled in your case - there is no way .NET COM Interop could interfere, assuming the RAWBUFFER.buffer pointer value got copied correctly.

     

    So, there are two possible explanations:

    1. The method signature you provided in the IDL file does not match the actual method signature of the host application.

     

    The IDL file is given with the host application and has been successfully used from our previous unmanaged c++ code

     

     Andrey Burlak wrote:

    2. The host application does not allocate the entire memory buffer, but instead relies on Structured Exception Handler to handle the Access Violation errors. Typically, such an application will commit the memory on-demand in its exception filter code and return EXCEPTION_CONTINUE_EXECUTION.

    A "plugin" written in unmanaged C++ will not see such Access Violation exceptions as long as it only uses C++ exception handling.

    However, the .NET Framework exposes every native exception as various Exception objects, in your case - AccessViolationException. Thus, the EXCEPTION_CONTINUE_EXECUTION trick is not supported while in managed code.

     

    From the API documentation of the application host, the buffer is fully allocated to (height*scanline) by the application.

    On our previous unmanaged c++ code, we don't trap SEH exception

    Monday, February 18, 2008 9:14 AM
  • To troubleshoot this issue, we really need the source code and the detailed repro steps to reproduce the problem, so that we can investigate the issue in house. It is not necessary that you send out the complete source of your project. We just need a simplest sample to reproduce the problem. You can remove any confidential information or business logic from it.


    You can send a sample project and repro steps in details to may email address which can be found in my personal profile page.

    Monday, February 18, 2008 9:18 AM
  • The host application is issue from a third party compagny, is closed source and protected by usb key.

    I will try to develop a fake application which mimic this behavior for the end of the week, and mail it to you.

    Thank's for your reply

     

     Feng Chen - MSFT wrote:

    To troubleshoot this issue, we really need the source code and the detailed repro steps to reproduce the problem, so that we can investigate the issue in house. It is not necessary that you send out the complete source of your project. We just need a simplest sample to reproduce the problem. You can remove any confidential information or business logic from it.


    You can send a sample project and repro steps in details to may email address which can be found in my personal profile page.

    Monday, February 18, 2008 4:57 PM