Microsoft KB Archive/264985

= BUG: ATL Connection Point Wizard-Generated Code for Event with [out]VARIANT* or [out]long* Argument Gives C4305 Warning =

Article ID: 264985

Article Last Modified on 12/11/2003

-

APPLIES TO


 * Microsoft Visual C++ 6.0 Enterprise Edition
 * Microsoft Visual C++ 6.0 Professional Edition
 * Microsoft Visual C++ 6.0 Standard Edition
 * Microsoft ActiveX Template Library 3.0

-



This article was previously published under Q264985



SYMPTOMS
The ATL Connection Point wizard generates a proxy class that implements a connection point for an outgoing interface. If an outgoing interface has an event that takes an argument of type [out]VARIANT* or [out]long*, the wizard generates incorrect code in the outgoing call (Fire_ method) for that event. The Visual C++ compiler gives the following two warnings when you call this Fire_ method in your code:

warning C4305: 'argument' : truncation from 'struct tagVARIANT *' to 'bool'

warning C4800: 'struct tagVARIANT *' : forcing value to bool 'true' or 'false' (performance warning)

warning C4305: 'argument' : truncation from 'long *' to 'bool'

warning C4800: 'long *' : forcing value to bool 'true' or 'false' (performance warning)



CAUSE
When you use the Connection Point Wizard, incorrect code is generated in the Fire_ method for the event that takes [out]VARIANT* or [out]long* as a parameter. For Event1, with VARIANT* and long* parameters pVar and pLongVal, it generates the following code in the Fire_Event1 method of the proxy class: pvars[0] = pVar; pvars[1] = pLongVal; You receive this error because ATL-generated code directly assigns a VARIANT* and a long* to a CComVariant type. Therefore, the compiler assumes that a CComVariant overloaded operator for these data types is defined; when the compiler does not find one, it considers these values as Boolean and the warning is generated.



RESOLUTION
The following are two workarounds for this problem:   Change the wizard-generated code from the following pvars[0] = pVar; pvars[1] = pLongVal; to the following: pvars[0].vt = VT_BYREF|VT_VARIANT; pvars[0].pvarVal = pVar; pvars[1].vt = VT_BYREF|VT_I4; pvars[1].plVal = pLongVal; The drawback of this approach is that every time that you add a method to your connection point interface and ask the wizard to implement the connection points, the earlier changes that you made will be overwritten and you will lose your changes. Make sure you back up your changes before allowing the wizard to implement the interface.   Modify the CComVariant class in the AtlBase.h file, and provide overloaded &quot;=&quot; operators for VARIANT* and long*. A sample implementation might resemble the following: CComVariant& operator=(long* nSrc) {  if (vt != VT_I4) {    InternalClear; vt = VT_BYREF|VT_I4; }  plVal = nSrc; return *this; }

CComVariant& operator=(const VARIANT* nSrc) {  InternalCopy(nSrc); return *this; } Make these modifications to a copy of the AtlBase.h file (for instance, FixAtlBase.h). Then, in Stdafx.h, comment out AtlBase.h and use FixAtlBase.h instead, as follows: // #include       #include &quot;FixAtlBase.h&quot; This technique works only in Debug or ReleaseMinDependency builds. This technique does not work in ReleaseMinSize builds because the ATL.dll file is used, not the code in FixAtlBase.h. 



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.



Steps to Reproduce Behavior
 Create a new ATL DLL/EXE project. Insert a simple object with connection point support.</li> Add a method named Event1 to the source(event) interface that takes a VARIANT* and long* as [out] parameters.</li> Compile the project.</li> Right-click the ATL class and click Implement Connection Point to start the Connection Point Wizard.</li> Select the event interface, and then click OK.</li>  Create a test method on the ATL object's incoming interface with VARIANT as a parameter, and call it &quot;Fire_Event1&quot;. STDMETHODIMP CTestQ::Test(VARIANT* pVar, long* pLong) {   Fire_Event1(pVar,pLong); return S_OK; }                       </li> Compile your application to see the warnings C4305 and C4800.</li></ol>

<div class="references_section">