HCTwinJava

I need to reimplement legacy COM interfaces (derived directly from IUnknown). A lot of methods on the old interfaces are equivalent to the following:


HRESULT setValue (const unsigned char* value);
HRESULT getValue (unsigned char* buffer, int bufferSize);


The pointers on both methods are in fact the addresses of unsigned char arrays, which may be allocated on the old COM client's stack. The COM server needs to use the pointers either to fetch a C-style string (in setValue method), or fill up the client's buffer up to the buffer size (in getValue method).

See the big problem (flaw) here


The COM server must be able to access the COM client's internal memory directly. But the problem is, that can't happen all the time, because COM will automatically marshal the pointers! So, more often than not, my implementation of the old COM interfaces can't see the client's internal memory (pointer values are changed automatically by COM).

Given the constraint that no change can be made to the old interfaces nor to the old COM clients, how can I reliably support this C-style behaviors on COM interfaces


FYI: old implementation seems to work just fine - amazing ! It used ATL 3.0 with "Apartment" threading. I use VC++ 2005.


Any comments or suggestions are welcome. Thank you!

Henry




Re: Visual C++ Language need help to deal with char* pointers on COM interfaces

Brian Kramer

In COM programming, strings should be represented as BSTRs (see SysAllocString, and related APIs). Arrays should be represented as SafeArrays. This should get you started.



Re: Visual C++ Language need help to deal with char* pointers on COM interfaces

HCTwinJava

thanks and 100% agreed. Unfortunately, seeing the flaw won't get me anywhere. As you can see from my post, that is exactly what's causing my big headache right now, because I have to support the flawed interfaces.


I did a lot of low-level COM programming work in the past. But I guess I don't know enough to "flawlessly" support the flaw of some ~10-year-old COM interfaces. As you can see, this is a delimma. But that's the reality. Not every1 knows of this or understands my explanation. And I happen to have to accomplish this "mission impossible", which was "assigned" to me by some "smartest" programmers years ago.

Actually, this is considered a very trivial task by some... And they have this choking proof: the interfaces have been used for years, and seem to be just fine; why do you keep telling me they are flawed ! !


So, instead of asking how to deal with char* pts on a COM interface, let me rephrase my question:

What are the exact conditions that must be satisfied in order to let a COM server "see" its client's internal memory address passed via the raw value of a raw pointer


Surely this can be done - at least sometimes. but I don't seem to know ALL of the conditions. Here are some things I tried, from which you might find something that I missed:

  • I once considered the use of free-threaded apartment for my coclass, but soon I realized that the interfaces were also designed in such a way that all client calls must be serialized. This essentially means I'm stuck with single-threaded apartment model.
  • If I can somehow "disable" COM marshalling yet somehow "guarantee" my COM dll will be loaded to the client's process, I guess my coclass will be able to treat the char* ptr as a pointer to the right memory.
  • I must have my COM server create in the same apartment of the client, in order to "disable" COM's auto marshalling. What's the best option here

I know, a flawed interface is flawed anyway. so my question is essentially: what's the best option for "covering" the design flaw if you were me, what would you do

Thanks in advance for any suggestions or comments!

Henry






Re: Visual C++ Language need help to deal with char* pointers on COM interfaces

Brian Kramer

If i were you, i'd do the right thing and get it done. Maintaining what you have appears to be taking up more time.



Re: Visual C++ Language need help to deal with char* pointers on COM interfaces

HCTwinJava

"In COM programming, strings should be represented as BSTRs (see SysAllocString, and related APIs). Arrays should be represented as SafeArrays."

- this is true only if automation support is desirable. COM does not mandate it. So, using char* ptr on COM interfaces does not break any COM principles.

To be accurate, the design flaw is that the getValue and setValue methods are not defined in a way to let COM know that our (unsigned) char* ptr is in fact a pointer to an array of characters. As a result, COM does not know that the raw value of the pointer should be preserved (or marshaleld as an array address) so that the server can read/write the characters beyond the 1st char pointed to by the ptr. Therefore, in order to make the whole thing work, COM must be convinced that no marshalling is needed, and the COM server must be able to see the client's memory. My question is: what's the least flawed option to achieve that

FYI, all the COM interfaces & clients I'm talking about have been used in a mission-critical system by many customers worldwide for a decade. All those programs were written by supposedly some of the smartest programmers in the world. Who's going to believe me that their interfaces are flawed My current project is to replace this old system while maintaining 100% backward compatibility. To be 100% backward compatible, I have to re-implement all the old interfaces (using the new solution as my backend of course)... sigh.






Re: Visual C++ Language need help to deal with char* pointers on COM interfaces

Brian Kramer

Yep, you're correct that this falls under COM Automation (IDispatch::Invoke does marshalling of BSTRs and SafeArrays).

Marshalling using DCOM and RPC should give you the lower level access you need. Try reading this article to see if it helps.