0

I have a COM interface with a following method definition (IDL notation):

SCODE GetText( [in, out] ULONG* pcwcBuffer,
              [out, size_is(*pcwcBuffer)] WCHAR* awcBuffer );

Typelib marshaling is used for COM+, the type library is registered, other methods of the interface work allright when called through COM+, but not this method.

The server side copies an array of WCHARs into the awcBuffer and its length into pwcBuffer, no buffer overrun ever occurs.

static const wchar_t* Text = L"Sample";
STDMETHODIMP CImpl::GetText( ULONG* bufferLength, WCHAR* buffer )
{
    const int length = wcslen( Text );
    *bufferLength = length;
    memcpy( buffer, Text, length * sizeof( WCHAR ) );
    return S_OK;
}

When the client calls this method through COM+ the buffer contents gets lost. Specifically only the first wide char is preserved - if the server copies "Sample" wide character string, the client only receives "S" string. The return value on the client size is S_OK, the buffer length returned to the client is exactly the same as what the server copied.

I finally switched to BSTR to workaround this problem but it's really interesting why the whole valid looking construct doesn't work.

What's the possible reason of the described behaviour?

4

3 回答 3

3

IIRC,typelib 编组器忽略 size_is 属性——因此,只有 1 个字符被编组。

于 2009-05-13T12:43:32.613 回答
2

J. 传球是对的。要使 typelib 编组器工作,COM 接口必须与 OLE 自动化兼容。typelib marshaller 是在 oleaut32.dll 中实现的,所以我猜名字里有线索。

[size_is] 是完全有效的 IDL,并编译成有效的类型库,但类型库封送器只能处理有效接口的子集。该子集通常称为 OLE 自动化。顺便说一句,VB6 客户端只能说 OLE 自动化,因此他们也无法使用您的界面。

尝试使用 IDL 中的 [oleautomation] 属性标记您的接口。它应该给你一个警告或错误消息,可能会指向你关于这个主题的更多信息。

在“普通”COM 中,您可以从 IDL 生成代理/存根 DLL 来进行编组,但恐怕我不记得 COM+ 是否会使用您的自定义编组代码,即使您费心构建它。

更新:在 Juval Lowy 的“COM 和 .NET 组件服务”一书中,我发现了这样的声明:“ ...配置的组件不能使用需要自定义封送处理的接口”。所以我猜这个接口永远不会在 COM+ 中工作。如果可以,请重新编写以使用 BSTR。

于 2009-05-13T12:53:33.707 回答
0

几个问题:

  • 你为什么不使用BSTR
  • 你有GetText函数的来源吗?
  • 函数返回的缓冲区大小是多少?
于 2009-05-13T12:13:45.987 回答