Solved

.Net Interop Problem with LPArray : COM Client throws Exception

Posted on 2002-06-18
33
552 Views
Last Modified: 2013-11-25
I need to know how to properly marshal the data from my legacy app to a .Net component. The integrity of the data must be kept. No memory leaks must occur in the solution. The solution should never fault. My legacy app uses the following IDL interface definition:
 
interface IMyInterface2 : IUnknown
{
 HRESULT doit( [in, size_is(msgLength)]UCHAR* msg, [in] ULONG msgLength );
};
 
When my legacy COM Client calls my .Net component that implements this interface, an access violation (0xC0000005) exception is thrown. I've tried everything and can not figure out why the exception is thrown in
the COM Client.
 
Here is the COM Client:
 
#include "stdafx.h"
#include "IMyInterface2_h.h"
#include "IMyInterface2_i.c"
 
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = S_OK;
hr = ::CoInitialize( NULL );
CLSID rcid = { 0x5F850215, 0x7AC2, 0x48b8, { 0xA8, 0xCF, 0xA0, 0x08, 0xF7, 0x33, 0xD6, 0x61 } };
 
{
CComPtr<IMyInterface2> iMyInterface2;
hr = iMyInterface2.CoCreateInstance( rcid, NULL, CLSCTX_INPROC_SERVER
);
UCHAR* pBytes = (UCHAR*)::CoTaskMemAlloc( 20 );
::ZeroMemory( pBytes, 20 );
iMyInterface2->doit( pBytes, 20 );
}
::CoUninitialize();
 
return 0;
}
 
The exception is thrown on the statement:
iMyInterface2->doit( pBytes, 20 );
The call never gets to the .Net component's method
 
And here is the .Net service component. The .Net component must be copied in the same directory as the COM client.
 
using System;
using System.Runtime.InteropServices;
 
namespace ComSrv
{
 [GuidAttribute("5F850215-7AC2-48b8-A8CF-A008F733D661")]
 public class MyClass : IMyInterface2
 {
  public void doit( byte[] msg, ulong msgLength )
  {
  }
 }
 
 [ComImport]
 [GuidAttribute("B55AFAEB-BC7D-4ca9-8065-F9A45FE378B6")]
 [InterfaceTypeAttribute  
ComInterfaceType.InterfaceIsIUnknown)]
 public interface IMyInterface2
 {
  void doit(
   [In, MarshalAs( UnmanagedType.LPArray, SizeParamIndex=1, ArraySubType=UnmanagedType.U1 )]byte[] msg, [In]ulong msgLength );
 }
}

0
Comment
Question by:Clearly
  • 15
  • 9
  • 3
  • +5
33 Comments
 
LVL 20

Expert Comment

by:Silvers5
ID: 7090533
does the com client calls your .net application using a user context that has enough permissions to do it? try to run the client as an administrator..
...It that .Net applications is pointing to a different memory processes..
0
 

Author Comment

by:Clearly
ID: 7090695
THey are both running under the exact same context
0
 

Author Comment

by:Clearly
ID: 7090742
THey are both running under the exact same context
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 7090756
Isn't as easy as it sounds. This article is pretty good, just read through it:

http://www.execpc.com/~gopalan/dotnet/classic_com/com.net_interop.html
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 7090761
You have posted this question twice. You can delete the other question in this topic area.

CJ
0
 

Author Comment

by:Clearly
ID: 7090920
I've posted twice because 500 is the limit and I want to award 1000.
0
 
LVL 22

Expert Comment

by:CJ_S
ID: 7090925
Aight. Checked the link?
0
 

Author Comment

by:Clearly
ID: 7090927
Let me be clear that I am not having a problem in general with .Net/COM interop. In fact, I've got many other interfaces working. The problem I am having is with this particular example which uses LPArray.
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091022
0xC0000005 as you have seen is an access violation, usually thrown when trying to access an invalid or NULL pointer.
Could ypu check if iMyInterface2 poiner is NULL after CoCreateInstance. There is a very chance that this interface never got created. I have tried to replicate your problem and I am getting the same problem. Only reason that COM interface was never created.


Have you tried using #import direcive with the TLB created from your managed .Net service component. I am sure that you must have doine it, but could you check if you REGASM the managed asembly so that gets registered with COM.

I have made some modification your code and after that i did not get any acces violation.
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091025
Code for managed service component..

using System;
using System.Runtime.InteropServices;

namespace ComSrv
{
     [GuidAttribute("B55AFAEB-BC7D-4ca9-8065-F9A45FE378B6")]
     [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
     public interface IMyInterface2
     {
          void doit(
               [In, MarshalAs( UnmanagedType.LPArray, SizeParamIndex=1, ArraySubType=UnmanagedType.U1 )]byte[] msg,
               [In]ulong msgLength );
     }

     /// <summary>
     /// Summary description for Class1.
     /// </summary>
     ///
     [GuidAttribute("5F850215-7AC2-48b8-A8CF-A008F733D661")]
     public class MyClass : IMyInterface2
     {
          public MyClass()
          {
               //
               // TODO: Add constructor logic here
               //
          }

          public void doit( byte[] msg, ulong msgLength )
          {
          }

     }
}
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091028
1.I compiled it...
2.used REGASM on this assembly to register with COM
3. Then i used TLBEXP to create TLB file
4. Copied TLB file to client folder.
5. Copied assembly to testclient folder

0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091030
Code for client application...You will notice that i have commented out some lines from your code. And replaced #include directives with #import directive

// TestApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
//#include "TestIdl_h.h"
//#include "TestIdl_i.c"
#import "MyNetService.tlb" raw_interfaces_only
using namespace MyNetService;


int _tmain(int argc, _TCHAR* argv[])
{
     HRESULT hr = S_OK;
     hr = ::CoInitialize( NULL );
     //CLSID rcid = { 0x5F850215, 0x7AC2, 0x48b8, { 0xA8, 0xCF, 0xA0, 0x08, 0xF7, 0x33, 0xD6, 0x61 } };

     {
          //CComPtr<IMyInterface2> iMyInterface2;
          //hr = iMyInterface2.CoCreateInstance( IID_IMyInterface2, NULL, CLSCTX_INPROC_SERVER
          //     );

          IMyInterface2Ptr ob(__uuidof(MyClass));
          UCHAR* pBytes = (UCHAR*)::CoTaskMemAlloc( 20 );
          ::ZeroMemory( pBytes, 20 );
          ob->doit( pBytes, 20 );
     }
     ::CoUninitialize();

     return 0;

}
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091032
Then I ran this test app.... I did not get any exceptions thrown at me.
But with your original code, I did get access violation when I called doIt method.

Naveen
0
 

Author Comment

by:Clearly
ID: 7091137
As I stated in my original post, I am attempting to load the .Net component into a legacy application. I do not have the luxury of modifying the legacy apllication. Using the #import would require changing my legacy apllication. I was able to reduce the interface problem to my legacy application in the example I posted. Thus, figuring out how to solve the problem in my example application should solve my legacy application problem. The solution I need is some change in the .Net component.
0
 

Author Comment

by:Clearly
ID: 7091171
BTW, the memory returned from CoTaskMemAlloc is non NULL and the CoCreateInstance returns S_OK.
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091186
Do you have luxury of debugging through the legacy application or not? ?Because that can make things little simple if you have because right now you are not even sure of the COM object got created or not.
Can you verify if the object was created at all? Access violation has to come from NULL pointer. Most likely its your COM object pointer.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 23

Expert Comment

by:naveenkohli
ID: 7091204
If you could really verify that interface is getting created and is not NULL, it will really help because it will eliminate one cause of this trouble.
0
 

Author Comment

by:Clearly
ID: 7091284
Verified that the interface is created. Before the call to CoCreateInstance, the value of iMyInterface2 is 0x00000000. After the call to CoCreateInstance, the value of iMyInterface2 is 0x0111002c.
0
 

Author Comment

by:Clearly
ID: 7091299
BTW, I've actually got 19,000 additional points that I am happy to reward if in fact I am satisfied with the solution and the solution comes quickly (24 hours).
0
 

Author Comment

by:Clearly
ID: 7091303
Here is more detail of the error emssage:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
0
 

Author Comment

by:Clearly
ID: 7091307
Here is the ILDasm signature for the .Net IMyInterface2:

instance void  doit([in] int32[]  marshal( unsigned int8[ + 1]) msg, [in] unsigned int64 msgLength) cil managed
0
 

Author Comment

by:Clearly
ID: 7091314
Scratch that...the IL is:

instance void  doit([in] unsigned int8[]  marshal(unsigned int8[ + 1]) msg,[in] unsigned int64 msgLength) cil managed
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7092571
Clearly,
Now I am also getting the same "Run time Check Failure" errors. I have done some reasearch on this. COuple of other people have run into this issue too. But the problem turned out to be wrong GUIDs used for CoCreateInstance. It seems that this is not the problem in your case. Could you check into this?

Naveen
0
 

Author Comment

by:Clearly
ID: 7092591
What should I check? The code is in the original post.

The COM Client instantiates:

CLSID rcid = { 0x5F850215, 0x7AC2, 0x48b8, { 0xA8, 0xCF, 0xA0, 0x08, 0xF7, 0x33, 0xD6, 0x61 } };

and the GuidAttribute set for my .Net component is:

[GuidAttribute("5F850215-7AC2-48b8-A8CF-A008F733D661")]
public class MyClass : IMyInterface2

What could be going wrong here?
0
 
LVL 20

Expert Comment

by:Silvers5
ID: 7092655
something similar was known in vb6 where I had to recompile the client component to conform to the server component..
http://dotnet.oreilly.com/news/complus_0801.html
but in C..
0
 
LVL 26

Expert Comment

by:EDDYKT
ID: 7092790
I don't quite understand

>>[ComImport]
>>[GuidAttribute("B55AFAEB-BC7D-4ca9-8065-F9A45FE378B6")]
>>[InterfaceTypeAttribute  
>>ComInterfaceType.InterfaceIsIUnknown)]
>>public interface IMyInterface2
>>{
>> void doit(
>>  [In, MarshalAs( UnmanagedType.LPArray, >>SizeParamIndex=1, ArraySubType=UnmanagedType.U1 )]byte[] >>msg,
>>[In]ulong msgLength );
>>}
>>}

Since UnmanagedType.U1 is known type by .NET. Do you really need to pass msgLength?

ie [In, MarshalAs( UnmanagedType.LPArray, >>SizeParamIndex=0, ArraySubType=UnmanagedType.U1 )]byte[] >>msg);
0
 

Author Comment

by:Clearly
ID: 7092867
EDDYKT :
How does .Net know how long the byte array is? It is not a string and does not have a NULL terminator. It is literally a chunk of memory.
0
 

Author Comment

by:Clearly
ID: 7094536
The question has been answered by someone else outside of experts-exchange. I will not reward anyone points for an answer.
0
 
LVL 23

Expert Comment

by:naveenkohli
ID: 7094575
COuld you please share the answer? This may benefit others.
0
 

Author Comment

by:Clearly
ID: 7094599
The problem was with the ulong marshalled parameter. The correct signature is listed below.

void doit( [In, MarshalAs( UnmanagedType.LPArray, SizeParamIndex=1, ArraySubType=UnmanagedType.U1 )]byte[] msg, [In]uint msgLength );

The change was from :
    [In]ulong msgLength
    to
    [In]uint msgLength
0
 
LVL 27

Expert Comment

by:Asta Cu
ID: 7136155
Have you been helped here, or is more needed?  This question is still open today.
":0) Asta
0
 
LVL 8

Expert Comment

by:zlatev
ID: 7964981
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

-  PAQ and points removed


Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !

Zlatin Zlatev
_____________
P.S. @Clearly, I do not suggest delete for the question because there are comments from experts that may be useful to other EE members with similar problem. You will loose your question points assigned in this question, unless you provide a starting point or a solution for the question within 7 days.

In that case my suggestion will be to redeem the points to you (PAQ and points not removed)
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 8018690
Finalized as proposed

modulo

Community Support Moderator
Experts Exchange
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now