I'm hoping somebody can shed some light on this problem. This code
has worked for some time in a production environment. Suddenly it
began blowing up in my development environment, and I can reproduce
the problem at will.
The code looks something like (simplified for clarity):
COM Client:
CComPtr<ITrcQueueItem> item;
HRESULT hr = w->AcquireItem(&item); // 0x80004002???
COM Server:
STDMETHODIMP CTrcSSBWorkflow::AcquireItem(ITrcQueueItem* *
pItem)
{
::CoCreateInstance( CLSID_QueueItem, NULL, CLSCTX_ALL,
IID_ITrcQueueItem, (void**)pItem);
pItem->set_Prop1(...);
// ...
return (S_OK);
}
When AcquireItem returns, everything appears to be hunky dory.
However, it returns to the bowels of the dispatch code, which
generates an exception, which I have captured in the debugger:
Call Stack on return from AcquireItem:
> rpcrt4.dll!NdrServerInitialize() + 0x288
rpcrt4.dll!NdrStubCall2() + 0x570
rpcrt4.dll!CStdStubBuffer_Invoke() + 0xc5
OLEAUT32.DLL!UserEXCEPINFO_free_local() + 0x2114
OLE32.DLL!HACCEL_UserMarshal() + 0x679
OLE32.DLL!CoGetCallContext() + 0x401
OLE32.DLL!CoGetCallContext() + 0x34d
OLE32.DLL!CoGetCallContext() + 0xb43
OLE32.DLL!HACCEL_UserMarshal() + 0x51b
OLE32.DLL!HACCEL_UserMarshal() + 0x394
OLE32.DLL!HACCEL_UserMarshal() + 0xab7
OLE32.DLL!CoGetCallContext() + 0xa76
USER32.DLL!SetWindowPlacement() + 0x50
USER32.DLL!TranslateMessageEx() + 0x605
USER32.DLL!DispatchMessageW() + 0xb
OLE32.DLL!StgOpenStorageEx() + 0x15ea
OLE32.DLL!StgOpenStorageEx() + 0x151d
Call Stack when exception is generated:
> KERNEL32.DLL!RaiseException() + 0x56
rpcrt4.dll!RpcRaiseException() + 0x1c
rpcrt4.dll!NdrServerContextNewUnmarshall() + 0x122
rpcrt4.dll!NdrPointerMarshall() + 0x29
rpcrt4.dll!CStdStubBuffer_Invoke() + 0xc5
OLEAUT32.DLL!UserEXCEPINFO_free_local() + 0x2114
OLE32.DLL!HACCEL_UserMarshal() + 0x679
OLE32.DLL!CoGetCallContext() + 0x401
OLE32.DLL!CoGetCallContext() + 0x34d
OLE32.DLL!CoGetCallContext() + 0xb43
OLE32.DLL!HACCEL_UserMarshal() + 0x51b
OLE32.DLL!HACCEL_UserMarshal() + 0x394
OLE32.DLL!HACCEL_UserMarshal() + 0xab7
OLE32.DLL!CoGetCallContext() + 0xa76
USER32.DLL!SetWindowPlacement() + 0x50
USER32.DLL!TranslateMessageEx() + 0x605
USER32.DLL!DispatchMessageW() + 0xb
OLE32.DLL!StgOpenStorageEx() + 0x15ea
OLE32.DLL!StgOpenStorageEx() + 0x151d
This results in hr being set to 0x80004002 and causes me great angst.
Any advice appreciated.
Thanks in advance,
JR
--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
"J. R. Antley" <john_...@rhco.com> wrote in message news:70038508.03011...@posting.google.com...
So why would he fail? *G* A little more information. I've also
developed some .NET interfaces with COM interop which implement
ITrcQueueManager and ITrcQueueItem interfaces.
The .NET code retrieves items into my queue from SQL Server, where the
old C++ implementation reads it from an Exchange Server, FYI, so you
might understand why I wanted to do this in the first place. Changing
a ProgID in the configuration utility, the application can be swapped
from one Queuing mechanism to the other.
Could this be causing my old ITrcQueueItem or ITrcQueueManager
implementation to be unhappy? I've looked, but I don't see how.
Regards,
JR
"Alexander Nickolov" <agnic...@mvps.org> wrote in message news:<OXlgn7ovCHA.2380@TK2MSFTNGP11>...
> Check the marshaling support for ITrcQueueItem (it's proxy/stub DLL).
> Looks like it's out of date with regard to the rest of the code...
>
> --
> =========================
> ============
> Alexander Nickolov
> Microsoft MVP [VC], MCSD
> email: agnic...@mvps.org
> MVP VC FAQ: http://www.mvps.org/vcfaq
> =========================
> ============
>
> "J. R. Antley" <john ant...@rhco.com> wrote in message
> news:70038508.03011...@posting.google.com...
> > Hi NG:
> >
> > I'm hoping somebody can shed some light on this problem. This code
> > has worked for some time in a production environment. Suddenly it
> > began blowing up in my development environment, and I can reproduce
> > the problem at will.
> >
> > The code looks something like (simplified for clarity):
> >
> > COM Client:
> >
> > CComPtr<ITrcQueueItem> item;
> > HRESULT hr = w->AcquireItem(&item); // 0x80004002???
> >
> > COM Server:
> >
> > STDMETHODIMP CTrcSSBWorkflow::AcquireItem(ITrcQueueItem* *
> > pItem)
> > {
> > ::CoCreateInstance( CLSID QueueItem, NULL, CLSCTX ALL,
> > IID ITrcQueueItem, (void**)pItem);
> > pItem->set Prop1(...);
> > // ...
> > return (S OK);
> > }
> >
> > When AcquireItem returns, everything appears to be hunky dory.
> > However, it returns to the bowels of the dispatch code, which
> > generates an exception, which I have captured in the debugger:
> >
> > Call Stack on return from AcquireItem:
> > > rpcrt4.dll!NdrServerInitialize() + 0x288
> > rpcrt4.dll!NdrStubCall2() + 0x570
> > rpcrt4.dll!CStdStubBuffer Invoke() + 0xc5
> > OLEAUT32.DLL!UserEXCEPINFO free local() + 0x2114
> > OLE32.DLL!HACCEL UserMarshal() + 0x679
> > OLE32.DLL!CoGetCallContext() + 0x401
> > OLE32.DLL!CoGetCallContext() + 0x34d
> > OLE32.DLL!CoGetCallContext() + 0xb43
> > OLE32.DLL!HACCEL UserMarshal() + 0x51b
> > OLE32.DLL!HACCEL UserMarshal() + 0x394
> > OLE32.DLL!HACCEL UserMarshal() + 0xab7
> > OLE32.DLL!CoGetCallContext() + 0xa76
> > USER32.DLL!SetWindowPlacement() + 0x50
> > USER32.DLL!TranslateMessageEx() + 0x605
> > USER32.DLL!DispatchMessageW() + 0xb
> > OLE32.DLL!StgOpenStorageEx() + 0x15ea
> > OLE32.DLL!StgOpenStorageEx() + 0x151d
> >
> > Call Stack when exception is generated:
> > > KERNEL32.DLL!RaiseException() + 0x56
> > rpcrt4.dll!RpcRaiseException() + 0x1c
> > rpcrt4.dll!NdrServerContextNewUnmarshall() + 0x122
> > rpcrt4.dll!NdrPointerMarshall() + 0x29
> > rpcrt4.dll!CStdStubBuffer Invoke() + 0xc5
> > OLEAUT32.DLL!UserEXCEPINFO free local() + 0x2114
> > OLE32.DLL!HACCEL UserMarshal() + 0x679
> > OLE32.DLL!CoGetCallContext() + 0x401
> > OLE32.DLL!CoGetCallContext() + 0x34d
> > OLE32.DLL!CoGetCallContext() + 0xb43
> > OLE32.DLL!HACCEL UserMarshal() + 0x51b
> > OLE32.DLL!HACCEL UserMarshal() + 0x394
> > OLE32.DLL!HACCEL UserMarshal() + 0xab7
--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
"J. R. Antley" <john_...@rhco.com> wrote in message news:70038508.03012...@posting.google.com...
"My" ITrcQueueManager is an abstract interface. I have a .IDL which
defines its methods and classes which implement the interface in C++.
I have another class which defines the same methods with the same GUID
in C#, so that my .NET implementation can implement the same
interface.
The problem is, that the marshalling implemented by both is tied to
that abstract interface. Thus, when TrcNetSqlQm registers itself, it
overwrites the registry settings for TrcQm governing its mashalling.
:( The custom marshalling built in to .NET is incompatible with the
automatic marshalling done by my C++ implementations.
The question becomes, how to fix this? To state it succinctly, uf
they implement the same interface, they should have the same GUID, I
am told. But the marshalling of the two implementations is different
and should be different. AFAIK, COM gives me know way to do this for
a dual interface.
Is there a way to have both Dlls registered at the same time,
implementing the same interface with the same GUID and different
marshalling strategies? If not, what is the best alternative?
Thanks again,
JR
<snipped to save bandwidth>
--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
"J. R. Antley" <john_...@rhco.com> wrote in message news:70038508.03012...@posting.google.com...
Actually, Alexander, you are mistaken about implementing existing
ActiveX / COM interfaces in C#. The way to do it IS to redefine the
interface in C#, then make a class that implements the interface.
Specify for the INTERFACE (not the class) the proper Guid attribute
and ComImport.
I can see why you have to do it that way, but it certainly would be
nice if TlbImp (or some other tool) would generate an interface in C#
for an existing COM interface, as others have pointed out.
"By placing the [ComImport] attribute on the C# interface you're
telling the
runtime that the definition of this interface is defined elsewhere in
COM."
Thanks to David Stucki of Microsoft for this gem.
When you do this, the registration of the .NET implementation no
longer clobbers the marshalling in the registry with the new typelib
GUID.
To find the marshalling parameters for a given interface, search for
the GUID of that interface in using RegEdit.
Cheers,
JR