I have a strange problem with some numbers going in and out of COM functions. In short, they are two's complements of what they should be. For example, i have a function


BEGIN_INTERFACE IAcadDocuments, IDispatch
.
.
.
STDMETHOD Open , :BSTR,:VARIANT,:ptr ptr IAcadDocument
.
.
.
END_INTERFACE

The variant parameter is defined in Autocad documentation like this:

ReadOnly
Variant; input-only; optional; Documents collection only
Default setting: FALSE
TRUE: Opens the drawing as a read-only drawing.
FALSE: Opens the drawing as a read-write drawing.


I want to open a drawing read-only, so i coded:


LOCAL openvar:VARIANT

mov openvar.vt,VT_BOOL
mov openvar.wReserved1,0
mov openvar.wReserved2,0
mov openvar.wReserved3,0
mov openvar.boolVal,[color=red]TRUE[/color]
.
.
.
invoke vf(pIAcadDocuments,IAcadDocuments,Open),ebx,openvar,ecx


This will open a drawing, but it is opened normally as read-write, not as read-only.
It opens as read-only with this:


mov openvar.vt,VT_BOOL
mov openvar.wReserved1,0
mov openvar.wReserved2,0
mov openvar.wReserved3,0
mov openvar.boolVal,[color=red]-1[/color]
.
.
.
invoke vf(pIAcadDocuments,IAcadDocuments,Open),ebx,openvar,ecx


Another example is a function (different COM server than the above)


DEFINE_DISPMETHOD IIfcSpace , GetInstance, 0Fh, METHOD, VT_I4


With this function, the return values should always be positive. But for example, when the return value should be 123, it is -123. What am i missing here?
Posted on 2003-10-17 16:56:38 by Janne
Just a thought, try VT_UI4 in the second one.
Posted on 2003-10-17 21:28:23 by Poimander
My guess is the alignment is wrong.

Your vairant should have the first word set as the type, followed by 3 words (6 bytes) of NULL's, then your boolean statment (1 or 0), should be 16 bytes long in total. Hex dump of your variant should look like:


0B 00 00 00 00 00 00 00 - 01 00 00 00 00 00 00 00
\---/ \---/


If your struc is not correct some how, it might make sence why things are backwards, since -1 is realy 'FF FF' (all 1's) while 1 is '01 00' with only one "TRUE" in fifteen bits "FALSE".

Have you tried initializing the variant with the prescibed api frunction VariantInit


You can also try this:


[b]ALIGN 4[/b]
LOCAL trueVar[16] :BYTE

lea edx trueVar
xor eax, eax
mov ecx, eax
inc ecx
mov WORD PTR [edx], 0Bh
mov [edx+2], ax
mov [edx+4], eax
mov [edx+8], ecx
mov [edx+12], eax


or this:
[b]ALIGN 4[/b]

LOCAL trueVar[16] :BYTE
invoke VariantInit, addr trueVar
lea edx trueVar
mov WORD PTR [edx], 0Bh
mov DWORD PTR [edx+8], TRUE
mov DWORD PTR [edx+12], NULL


:NaN:
Posted on 2003-10-17 21:29:06 by NaN
Hi Janne,

-1 as TRUE looks absolutely ok for me. The VARIANT type comes from VB, where TRUE is always -1.

For the other example I have no explanation, though
Posted on 2003-10-18 01:23:41 by japheth
Thanks.

I just wonder, why they equ True -1.
Posted on 2003-10-18 02:11:16 by Janne
Wow, I didnt realize that VB did this! (not that i use VB all that much).

I guess since the default stack size is 32 bits it does a 'sign extend' equivalent for booleans (since there is no such feature in assembly). The result would then be the -1 value when observing a 32 bit element in memory. I can say that this certainly balances the difference between the two, FALSE is all 0000h and TRUE is FFFFh. The way the windows API works is FALSE is 0000h and TRUE being 0001h. When you look at the latter its 99% on its way to being FALSE anyways ;)

Regards,
:NaN:
Posted on 2003-10-18 15:18:44 by NaN
Using -1 for TRUE probably comes from the BASIC language itself, as it does not support logical NOT, AND, OR & XOR, just bitwise operations. So NOT -1 equals 0... :P
Posted on 2003-10-18 17:52:48 by QvasiModo
Hi QvasiModo,

That is certainly true for the Microsoft BASIC family (especially Visual Basic). I am not sure that this is true of other flavors of BASIC. For NaN's purposes, though, you have done a good job of explaining Microsoft's variant format.

Charles
Posted on 2003-10-20 10:14:14 by cdquarles
I was under the impression that FALSE==NULL and TRUE!=NULL
Therefore anything not zero is TRUE.
I would be willing to bet that internally the VB runtimes use an OR reg,reg or similar "is-it-zero-or-not" test - can anyone confirm this?
Posted on 2003-10-29 03:22:30 by Homer
Hi EvilHomer2k,

False = 0000_0000h and a bitwise NOT False is FFFF_FFFFh or -1. I don't know the exact machine code that the Microsoft compilers output during compilation, but I suspect that they use a not reg and check the zero or sign flags. Microsoft Visual Basic (not VB .NET) use either a vbrunx00.dll or msvbvmx0.dll and the msvcrt.dlls. VB .NET uses the common language runtime, which IIRC is the C style bool, 0 for false and 1 for true.

Charles
Posted on 2003-10-29 22:15:04 by cdquarles

I was under the impression that FALSE==NULL and TRUE!=NULL
Therefore anything not zero is TRUE.

At least in the BASIC flavors I have tried (MS, under DOS) the IF statement would consider any expression that resolves to a nonozero value as TRUE. Comparison operators were just like the rest - they return a numerical result. So you could evaluate a variable, or store the result of a comparison in a variable for later checking (it was a BASIC optimization many people didn't know about :) ).
Since VB is based on MS versions of BASIC under DOS, all of that probably still holds true. But of course I'm just guessing.
Posted on 2003-10-30 16:05:29 by QvasiModo