Len() or LenB() to get structure size for API call? 
Author Message
 Len() or LenB() to get structure size for API call?

Hi all

Say an API call takes a structure, and the size of that structure in bytes,
as two parameters.

I thought you had to use LenB() - not Len() - to get the proper size -
given that Len() counts characters, and LenB() counts bytes.

However, the example code given in Q189249 ("HOWTO: Determine Which 32-Bit
Windows Version Is Being Used") uses the explicit constant 148 for the
length of the OSVERSIONINFO structure - which is:

        dwOSVersionInfoSize As Long     '    4 bytes.
        dwMajorVersion As Long             '    4
        dwMinorVersion As Long             '    4
        dwBuildNumber As Long              '    4
        dwPlatformId As Long                  '    4
        szCSDVersion As String * 128     ' 256
                                                           -------------
                                                      total:  276

Len() of this structure is 148. LenB() is 276.

Is the example article correct in using 148, or should it use 256, or
(preferably) LenB(OSVERSIONINFO)?

TIA,
TC



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

TC,

Normally, when using API functions, you want LenB(),
as it is taking the fact that Unicode characters are 2 bytes
rather than 1 into account.

Use Len() when you only need to take the _number_ of
characters into account.

However, if you look more closely at that example, it's using the
ANSI version of the GetVersionEx call [GetVersionExA].

If you were to use GetVersionExW for any reason, then you would
lose the first half of szCSDVersion when passing 148.

It is indeed confusing to begin with. :>

Quote:

>Hi all

>Say an API call takes a structure, and the size of that structure in bytes,
>as two parameters.
...

>However, the example code given in Q189249 ("HOWTO: Determine Which 32-Bit
>Windows Version Is Being Used") uses the explicit constant 148 for the
>length of the OSVERSIONINFO structure - which is:

...
>Len() of this structure is 148. LenB() is 276.

>Is the example article correct in using 148, or should it use 256, or
>(preferably) LenB(OSVERSIONINFO)?

>TIA,
>TC



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

AHA!

Many thanks Bruce.

I guess the devil is in the detail.

TC



Quote:

> TC,

> Normally, when using API functions, you want LenB(),
> as it is taking the fact that Unicode characters are 2 bytes
> rather than 1 into account.

> Use Len() when you only need to take the _number_ of
> characters into account.

> However, if you look more closely at that example, it's using the
> ANSI version of the GetVersionEx call [GetVersionExA].

> If you were to use GetVersionExW for any reason, then you would
> lose the first half of szCSDVersion when passing 148.

> It is indeed confusing to begin with. :>


> >Hi all

> >Say an API call takes a structure, and the size of that structure in
bytes,
> >as two parameters.
> ...

> >However, the example code given in Q189249 ("HOWTO: Determine Which
32-Bit
> >Windows Version Is Being Used") uses the explicit constant 148 for the
> >length of the OSVERSIONINFO structure - which is:

> ...
> >Len() of this structure is 148. LenB() is 276.

> >Is the example article correct in using 148, or should it use 256, or
> >(preferably) LenB(OSVERSIONINFO)?

> >TIA,
> >TC



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
I would disagree with Bruce when he says:

"Normally, when using API functions, you want LenB(), as it is taking the
fact that Unicode characters are 2 bytes rather than 1 into account."

This does not take into account the fact that VB, although it uses Unicode
internally, automatically converts Unicode to ANSI or ANSI to Unicode when
passing strings to or from API functions.  I suggest that it is in fact
"normal" to use the ANSI version of the API call and, because of the
automatic conversion, it is "normal" to use Len() rather than LenB().

John.....

Quote:

> AHA!

> Many thanks Bruce.

> I guess the devil is in the detail.

> TC



> > TC,

> > Normally, when using API functions, you want LenB(),
> > as it is taking the fact that Unicode characters are 2 bytes
> > rather than 1 into account.

> > Use Len() when you only need to take the _number_ of
> > characters into account.

> > However, if you look more closely at that example, it's using the
> > ANSI version of the GetVersionEx call [GetVersionExA].

> > If you were to use GetVersionExW for any reason, then you would
> > lose the first half of szCSDVersion when passing 148.

> > It is indeed confusing to begin with. :>


> > >Hi all

> > >Say an API call takes a structure, and the size of that structure in
> bytes,
> > >as two parameters.
> > ...

> > >However, the example code given in Q189249 ("HOWTO: Determine Which
> 32-Bit
> > >Windows Version Is Being Used") uses the explicit constant 148 for the
> > >length of the OSVERSIONINFO structure - which is:

> > ...
> > >Len() of this structure is 148. LenB() is 276.

> > >Is the example article correct in using 148, or should it use 256, or
> > >(preferably) LenB(OSVERSIONINFO)?

> > >TIA,
> > >TC



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

Ok. Just to be sure I understand ... I can use "A" (ANSII) or "W" (Unicode)
version APIs as I choose, but I should use Len() with the "A" ones, and
LenB() with the "W" ones. Correct?

TIA,
TC



Quote:
> I would disagree with Bruce when he says:

> "Normally, when using API functions, you want LenB(), as it is taking the
> fact that Unicode characters are 2 bytes rather than 1 into account."

> This does not take into account the fact that VB, although it uses
Unicode
> internally, automatically converts Unicode to ANSI or ANSI to Unicode
when
> passing strings to or from API functions.  I suggest that it is in fact
> "normal" to use the ANSI version of the API call and, because of the
> automatic conversion, it is "normal" to use Len() rather than LenB().

> John.....


> > AHA!

> > Many thanks Bruce.

> > I guess the devil is in the detail.

> > TC



> > > TC,

> > > Normally, when using API functions, you want LenB(),
> > > as it is taking the fact that Unicode characters are 2 bytes
> > > rather than 1 into account.

> > > Use Len() when you only need to take the _number_ of
> > > characters into account.

> > > However, if you look more closely at that example, it's using the
> > > ANSI version of the GetVersionEx call [GetVersionExA].

> > > If you were to use GetVersionExW for any reason, then you would
> > > lose the first half of szCSDVersion when passing 148.

> > > It is indeed confusing to begin with. :>


> > > >Hi all

> > > >Say an API call takes a structure, and the size of that structure in
> > bytes,
> > > >as two parameters.
> > > ...

> > > >However, the example code given in Q189249 ("HOWTO: Determine Which
> > 32-Bit
> > > >Windows Version Is Being Used") uses the explicit constant 148 for
the
> > > >length of the OSVERSIONINFO structure - which is:

> > > ...
> > > >Len() of this structure is 148. LenB() is 276.

> > > >Is the example article correct in using 148, or should it use 256,
or
> > > >(preferably) LenB(OSVERSIONINFO)?

> > > >TIA,
> > > >TC



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
Hi TC,

Always use Len() to obtain the size of a structure, because it takes
into account all the padding needed for byte alignment. Also, as it was
already pointed, each time VB passes a string to an API, it converts it
to ANSI first. So, if want to call the UNICODE version of an API that
takes a string you need to put the string in to a byte array, adding a
terminating 0 byte and pass the array instead.

Regards,
         Stoil

Quote:

> Ok. Just to be sure I understand ... I can use "A" (ANSII) or "W" (Unicode)
> version APIs as I choose, but I should use Len() with the "A" ones, and
> LenB() with the "W" ones. Correct?

> TIA,
> TC



> > I would disagree with Bruce when he says:

> > "Normally, when using API functions, you want LenB(), as it is taking the
> > fact that Unicode characters are 2 bytes rather than 1 into account."

> > This does not take into account the fact that VB, although it uses
> Unicode
> > internally, automatically converts Unicode to ANSI or ANSI to Unicode
> when
> > passing strings to or from API functions.  I suggest that it is in fact
> > "normal" to use the ANSI version of the API call and, because of the
> > automatic conversion, it is "normal" to use Len() rather than LenB().

> > John.....


> > > AHA!

> > > Many thanks Bruce.

> > > I guess the devil is in the detail.

> > > TC



> > > > TC,

> > > > Normally, when using API functions, you want LenB(),
> > > > as it is taking the fact that Unicode characters are 2 bytes
> > > > rather than 1 into account.

> > > > Use Len() when you only need to take the _number_ of
> > > > characters into account.

> > > > However, if you look more closely at that example, it's using the
> > > > ANSI version of the GetVersionEx call [GetVersionExA].

> > > > If you were to use GetVersionExW for any reason, then you would
> > > > lose the first half of szCSDVersion when passing 148.

> > > > It is indeed confusing to begin with. :>


> > > > >Hi all

> > > > >Say an API call takes a structure, and the size of that structure in
> > > bytes,
> > > > >as two parameters.
> > > > ...

> > > > >However, the example code given in Q189249 ("HOWTO: Determine Which
> > > 32-Bit
> > > > >Windows Version Is Being Used") uses the explicit constant 148 for
> the
> > > > >length of the OSVERSIONINFO structure - which is:

> > > > ...
> > > > >Len() of this structure is 148. LenB() is 276.

> > > > >Is the example article correct in using 148, or should it use 256,
> or
> > > > >(preferably) LenB(OSVERSIONINFO)?

> > > > >TIA,
> > > > >TC



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

Quote:

> Always use Len() to obtain the size of a structure, because it takes
> into account all the padding needed for byte alignment.

Actually, Stoil, with this structure

Private Type x
  t As Integer
  s As Long
End Type

dim a as x

len(a) returns 6, lenb(a) returns 8; the correct length is, of course,
8, because of the padding you rightly note.



Tue, 22 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

Thanks Stoil & Jeff for your replies.

What about using LenB() in all cases, regardless of which APIs one is
calling?

Then, you're safe in the worst-case situation.

The few bytes wasted by this approach should not be significant, in typical
VB-calling-win32-API situations.

Yes? No?

TC



Quote:

> > Always use Len() to obtain the size of a structure, because it takes
> > into account all the padding needed for byte alignment.

> Actually, Stoil, with this structure

> Private Type x
>   t As Integer
>   s As Long
> End Type

> dim a as x

> len(a) returns 6, lenb(a) returns 8; the correct length is, of course,
> 8, because of the padding you rightly note.



Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
No. That is a bad idea. Len() is almost always correct, and
passing the wrong number can have all sorts of bad
consequences. Just try Len().  LenB() is an interesting
thing toi try if you are having problems. But passing LenB,
especially when there are strings involved that are
converted from Unicode automatically, can easily cause an AV
or GPF as you walk off the end of a buffer.

--
MichKa

-------------------------------------
don't send questions by e-mail unless
you're paying for it. (TANSTAAFL!) :-)

random junk of dubious value is at:
http://www.trigeminal.com


Quote:

> Thanks Stoil & Jeff for your replies.

> What about using LenB() in all cases, regardless of which
APIs one is
> calling?

> Then, you're safe in the worst-case situation.

> The few bytes wasted by this approach should not be

significant, in typical
Quote:
> VB-calling-win32-API situations.

> Yes? No?

> TC




> > > Always use Len() to obtain the size of a structure,
because it takes
> > > into account all the padding needed for byte
alignment.

> > Actually, Stoil, with this structure

> > Private Type x
> >   t As Integer
> >   s As Long
> > End Type

> > dim a as x

> > len(a) returns 6, lenb(a) returns 8; the correct length
is, of course,
> > 8, because of the padding you rightly note.



Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

Quote:
>Len() is almost always correct

except when it's not? <g>


Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
My point is that when you are not sure, Len is more likely
to be right. That means that if you have no knowledge of
which to use and you start with LenB instead of Len, then
you need to spend some time learning how to write smart
code.

But thinking that "bigger is better" is sure to get you in
trouble more often than not. So if you do insist on going
that way, I know three things about you:

1) you are being paid by the hour
2) you are not having your methods peer reviewed to make
sure those hours are being spent efficiently
3) You either save your work often or redo a lot of work

Extreme view? Maybe. But smart code is largely due to an
attitude of constructive laziness.... making educated
guesses when you are not sure to maximize the chances of
getting it right earlier rather than later.

--
MichKa

-------------------------------------
don't send questions by e-mail unless
you're paying for it. (TANSTAAFL!) :-)

random junk of dubious value is at:
http://www.trigeminal.com


Quote:
> >Len() is almost always correct

> except when it's not? <g>



Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
Wait wait wait wait

We are discussing how to make assumptions that may prove to be
groundless and how to recover from them when they are groundless.  In
the simple (stupid?) case I presented, len() ignores internal buffering
and returns an incorrect value which will 'flavor' all values returned
in that UDT, which I may not discover for awhile and which may be a bear
to debug; if I use lenb(), I have no problem. Somehow that proves I am
an inadequate programmer?  (I'll bet it _kills_ you when you spend 2
hours debugging something and a new guy walking by looks over your
shoulder and points out your error, doesn't it?)

Had you responded that one should _never_ permit implicit buffering in a
UDT, I would agree 100%.  Had you said that one should learn the
behavior of function calls, what they expect and what they return, I
would have no problem.  Instead, apparently, in a peer review you will
ask why the guy used lenb() but not ask why he used len(), or, if you
do, 'I guessed' is a good answer in the second case and not in the
first!  

I've worked with guys like you . . . but never on purpose.



Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
My post was in response to the request made by the orginal
poster... to wit, should you ALWAYS use LenB. I stand by my
post as an answer to that question.

In truth, in my personal habits, I would prefer to
understand the API call as a part of making the decision.
Not everyone feels as comfortable in MSDN since its not very
tailored to VB, but it doesn't bother me so thats where I
start.

But short of that, statistically Len is less likely to cause
problems then LenB, so if you are doing it by trial, then
using Len() and saving your work first is the best idea for
writing smart code in VB that uses API calls.

--
MichKa

-------------------------------------
don't send questions by e-mail unless
you're paying for it. (TANSTAAFL!) :-)

random junk of dubious value is at:
http://www.trigeminal.com


Quote:
> Wait wait wait wait

> We are discussing how to make assumptions that may prove
to be
> groundless and how to recover from them when they are
groundless.  In
> the simple (stupid?) case I presented, len() ignores
internal buffering
> and returns an incorrect value which will 'flavor' all
values returned
> in that UDT, which I may not discover for awhile and which
may be a bear
> to debug; if I use lenb(), I have no problem. Somehow that
proves I am
> an inadequate programmer?  (I'll bet it _kills_ you when
you spend 2
> hours debugging something and a new guy walking by looks
over your
> shoulder and points out your error, doesn't it?)

> Had you responded that one should _never_ permit implicit
buffering in a
> UDT, I would agree 100%.  Had you said that one should
learn the
> behavior of function calls, what they expect and what they
return, I
> would have no problem.  Instead, apparently, in a peer
review you will
> ask why the guy used lenb() but not ask why he used len(),
or, if you
> do, 'I guessed' is a good answer in the second case and
not in the
> first!

> I've worked with guys like you . . . but never on purpose.



Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?
I agree.  But, when in doubt, run a couple of tests - it's usually
pretty easy to figure out what is happening pretty quickly, and much
easier than coming back a month later to see what's wrong.  (And
VB/Windows has gotten so complex it's certainly not possible for me to
internalize all the answers - I feel good just knowing a lot of the
questions!)

Two bugs that have scared the bejeezuz out of me (neither mine), so
simple, so obvious, so deadly:

1. One guy was calling a sub with a parameter he expected to be modified
(ergo byref) and used the calling syntax 'subx(paramx)' - since it was
expected almost always to return 0, he never saw a problem with it,
until a month later or so he _knew_ he should be getting a different
value and after a full day of debugging realized he was forcing byval
and could never get anything returned . . .

2. At my latest shop, I found a 'core' function which has apparently
been used for years to extract the time value from a given date-time:
        x = thatdt - clng(thatdt)
which, of course, works great until noon and then starts backing down to
'8 a.m.' at 4 p.m. etc  - never been reviewed, never been debugged,
never caused a recognized problem . . . <g>



Wed, 23 Jan 2002 03:00:00 GMT  
 Len() or LenB() to get structure size for API call?

Thanks Michael. I'll do it that way (& read up more on the API calls!)

TC



Quote:
> No. That is a bad idea. Len() is almost always correct, and
> passing the wrong number can have all sorts of bad
> consequences. Just try Len().  LenB() is an interesting
> thing toi try if you are having problems. But passing LenB,
> especially when there are strings involved that are
> converted from Unicode automatically, can easily cause an AV
> or GPF as you walk off the end of a buffer.

> --
> MichKa

> -------------------------------------
> don't send questions by e-mail unless
> you're paying for it. (TANSTAAFL!) :-)

> random junk of dubious value is at:
> http://www.trigeminal.com



> > Thanks Stoil & Jeff for your replies.

> > What about using LenB() in all cases, regardless of which
> APIs one is
> > calling?

> > Then, you're safe in the worst-case situation.

> > The few bytes wasted by this approach should not be
> significant, in typical
> > VB-calling-win32-API situations.

> > Yes? No?

> > TC




> > > > Always use Len() to obtain the size of a structure,
> because it takes
> > > > into account all the padding needed for byte
> alignment.

> > > Actually, Stoil, with this structure

> > > Private Type x
> > >   t As Integer
> > >   s As Long
> > > End Type

> > > dim a as x

> > > len(a) returns 6, lenb(a) returns 8; the correct length
> is, of course,
> > > 8, because of the padding you rightly note.



Thu, 24 Jan 2002 03:00:00 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. LenB or Len

2. Len function for structure variable

3. Getting at data in structure returned as a long pointer (Win API)

4. Passing Structures to API Calls

5. How to pass an array of structures in an API call

6. string pointer in structure for API calls

7. Declaration of non Win API call and structures

8. Declaration of non Win API call and structures

9. call VC DLL with structure contains pointer of the structure to next

10. call VC DLL with structure contains pointer of the structure to next

11. API for getting the size of a directory

12. Assist in API Call to Check Screen Size

 

 
Powered by phpBB® Forum Software