Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MFC ActiveX (VARIANT_BOOL) type methods always return TRUE

133 views
Skip to first unread message

Anders Sandberg

unread,
Sep 15, 2004, 3:03:38 PM9/15/04
to
Visual Studio .NET 2003, Windows 2000 SP4, Unmanaged code.

Hi I just finished writing an MFC ActiveX control created with the wizard.
Most methods are VARIANT_BOOL (they return either VARIANT_TRUE or
VARIANT_FALSE)

When using this control in a client the wrappers converts the VARIANT_BOOL
type to BOOL (witch doesn't bather me) BUT the returned value is always TRUE
even though
the methods (for testing purposes) does nothing but return VARIANT_FALSE.

Now 99.9% of the time when I try to blame things on Microsoft I'm proven
wrong but this has got to be some kind of a bug...!
What do I do?

(I inserted the control in a dialog template and added a member variable for
it so the wrappers were generated)

thanx and regards
Anders Sandberg

RNEELY

unread,
Sep 15, 2004, 4:11:03 PM9/15/04
to
In Afx.h:
#define FALSE 0
#define TRUE 1

In wtypes.h:
#define VARIANT_TRUE ((VARIANT_BOOL)0xffff)
#define VARIANT_FALSE ((VARIANT_BOOL)0)

Additionally C++ native
true == 1;
false == 0;

Since the defintions of TRUE, VARIANT_TRUE, and true vary with one another I
rarely ever test a flag as follows:
if(TRUE == bFlag) //... bad
if(VARIANT_TRUE == bFlag) //... bad
if(true == bFlag) //... bad

Rather, since the defintions of FALSE, VARIANT_FALSE, and false are all the
same it is better to test for a true conditions as not false
if(FALSE != bFlag) //... better
if(VARIANT_FALSE != bFlag) //... better
if(false != bFlag) //... better

Or, since non-zero is true in C++ the best check can be:
if(bFlag) // ... best, works for TRUE, VARIANT_TRUE, and true
else //... best, works for FALSE, VARIANT_FALSE, and false

Your wrapper probable has some auto generated code that is testing to see if
a VARIANT_BOOL flag == TRUE which can never be true. Modify the code to use
one of the above techiques - or you can properly convert as follows:
VARIANT_BOOL vb = VARIANT_TRUE;
BOOL B;
bool b;
B = (VARIANT_FALSE != vb); // TRUE == B // also true == B
b = false;
vb = B ? VARIANT_TRUE : VARIANT_FALSE; // vb = VARIANT_TRUE;
vb = b ? VARIANT_TRUE : VARIANT_FALSE; // vb = VARIANT_FALSE;

Regards,
-Ron

Anders Sandberg

unread,
Sep 15, 2004, 4:37:05 PM9/15/04
to
Hi Ron and thanx for your reply

I'm not sure I understand you correctly but I don't see how this could be
the problem. Since BOOL is a typedefd int and VARIANT_FALSE is defined 0 I
still don't understand why
the wrapper always retrievs 1 as the result as follows:

BOOL AsyncWrite(short nBlockIndex, short nByteIndex, VARIANT *
pvtSafeArrayI2, long lTimeOutMs)
{
BOOL result;
static BYTE parms[] = VTS_I2 VTS_I2 VTS_PVARIANT VTS_I4 ;
InvokeHelper(0x8, DISPATCH_METHOD, VT_BOOL, (void*)&result, parms,
nBlockIndex, nByteIndex, pvtSafeArrayI2, lTimeOutMs);
return result;
}


thanks for your concern!
Anders


"RNEELY" <RNE...@discussions.microsoft.com> skrev i meddelandet
news:4BE65B7D-4D6D-406E...@microsoft.com...

Anders Sandberg

unread,
Sep 15, 2004, 5:47:50 PM9/15/04
to
Hi there.

I found a bug and I know an easy way to fix it. (I'm not sure it's the best
way to report it here but it's so easy to fix. so...)

Bug: If you try to add a custom method to your MFC ActiveX control interface
and specify VARIANT_BOOL as a result type you will ALWAYS GET VARIANT_TRUE
result.

Explanation: That is because of the following:
1. File oledisp1.cpp line 1024

Here you dispatch (and execute) function implementing your method.
dwResult = pfnDispatch(pfn, pStack, nSizeArgs);

So you see that dwResult is a DWORD variable and VARIANT_BOOL is an unsigned
short type. Since _AfxDispatchCall (which is actuallty being called here)
has __declspec(naked) modificator and uses asm (see olecall.cpp file, line
29), it can set only lower 2 bytes of dwResult. So after this line dwResult
can look something like 0x10020000 (false) or 0x1002ffff (true, VARIANT_TRUE
is a definition for -1)

2. The same file (oledisp1.cpp), a few lines after - line 1093

Here you assign return value
V_BOOL(pvarResult) = (VARIANT_BOOL)(dwResult != 0 ? -1 : 0);

So, you see that you will never get 0! (-1 is a VARIANT_TRUE constant).

Fix:
You can fix line 1093 (as it5 it the easiest way to fix this).
You can change line 1093 as following:
V_BOOL(pvarResult) = (VARIANT_BOOL)((dwResult & 0xFFFF) != 0 ? -1 : 0);

With best regards,
Mike Berman.


"Anders Sandberg" <anders....@nospam.se> wrote in message
news:eMs12a1m...@TK2MSFTNGP10.phx.gbl...

smiley_smile.gif

RNEELY

unread,
Sep 16, 2004, 11:05:05 AM9/16/04
to
Instead of messing with the MFC source code would the following work?

BOOL AsyncWrite(short nBlockIndex, short nByteIndex, VARIANT *
pvtSafeArrayI2, long lTimeOutMs)
{
DWORD result;
static BYTE parms[] = VTS_I2 VTS_I2 VTS_PVARIANT VTS_I4 ;
InvokeHelper(0x8, DISPATCH_METHOD, VT_BOOL, (void*)&result, parms,
nBlockIndex, nByteIndex, pvtSafeArrayI2, lTimeOutMs);
return ((result&0xffff)==VARIANT_FALSE ? FALSE : TRUE);

Anders Sandberg

unread,
Sep 16, 2004, 12:42:15 PM9/16/04
to
Well compared to the mess of rebuilding the mfc dll's its a brilliant
workaround! Thanks!


"RNEELY" <RNE...@discussions.microsoft.com> skrev i meddelandet

news:AF7E0262-95EE-434E...@microsoft.com...

0 new messages