Len() or LenB() to get structure size for API call?
Author |
Message |
TC #1 / 16
|
 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 |
|
 |
Bruce M. Simpso #2 / 16
|
 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 |
|
 |
TC #3 / 16
|
 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 |
|
 |
John Keysto #4 / 16
|
 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 |
|
 |
TC #5 / 16
|
 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 |
|
 |
Stoil Marino #6 / 16
|
 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 |
|
 |
Jeff Ashle #7 / 16
|
 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 |
|
 |
TC #8 / 16
|
 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 |
|
 |
mich #9 / 16
|
 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 |
|
 |
Jeff Ashle #10 / 16
|
 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 |
|
 |
mich #11 / 16
|
 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 |
|
 |
Jeff Ashle #12 / 16
|
 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 |
|
 |
mich #13 / 16
|
 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 |
|
 |
Jeff Ashle #14 / 16
|
 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 |
|
 |
TC #15 / 16
|
 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 |
|
|
Page 1 of 2
|
[ 16 post ] |
|
Go to page:
[1]
[2] |
|