Always the stupid bugs...

| | Comments (13)

This was in a side project of mine for the WFS that I am working on. Let's see who can spot the bug:
[rbcode]Private Function capGetDriverDescription(wDriver as Integer, ByRef lpszName as string, ByRef lpszVer as string) As Boolean
#if TargetWin32
Soft Declare Function capGetDriverDescriptionW Lib "avicap32" (wDriver as Integer, lpszName as WString, _
cbName as Integer, lpszVer as WString cbVer as Integer) as Boolean
Soft Declare Function capGetDriverDescriptionA Lib "avicap32" (wDriver as Integer, lpszName as CString, _
cbName as Integer, lpszVer as CString, cbVer as Integer) as Boolean

dim name as new MemoryBlock( 2048 )
dim vers as new MemoryBlock( 2048 )
dim ret as Boolean

if System.IsFunctionAvailable( "capGetDriverDescriptionW", "avicap32" ) then
ret = capGetDriverDescriptionW( wDriver, name, name.Size, vers, vers.Size )
lpszName = name.WString( 0 )
lpszVer = vers.WString( 0 )
elseif System.IsFunctionAvailable( "capGetDriverDescriptionA", "avicap32" ) then
ret = capGetDriverDescriptionA( wDriver, name, name.Size, vers, vers.Size )
lpszName = name.CString( 0 )
lpszVer = vers.CString( 0 )
else
ret = false
end if

return ret
#endif
End Function[/rbcode]
The code was being called like this:[rbcode]
#if TargetWin32 then
Dim strName as String
Dim strVer as String
Dim ret( -1 ) as String
Dim i as Integer = 0

while capGetDriverDescription( i, strName, strVer )
ret.Append( strName )

i = i + 1
wend

return ret
#endif[/rbcode]MSDN has this to say about the capGetDriverDescription method:


capGetDriverDescription
The capGetDriverDescription function retrieves the version description of the capture driver.

BOOL VFWAPI capGetDriverDescription(
WORD wDriverIndex,
LPSTR lpszName,
INT cbName,
LPSTR lpszVer,
INT cbVer
);
Parameters

wDriverIndex

Index of the capture driver. The index can range from 0 through 9.

Plug-and-Play capture drivers are enumerated first, followed by capture drivers listed in the registry, which are then followed by capture drivers listed in SYSTEM.INI.

lpszName

Pointer to a buffer containing a null-terminated string corresponding to the capture driver name.

cbName

Length, in bytes, of the buffer pointed to by lpszName.

lpszVer

Pointer to a buffer containing a null-terminated string corresponding to the description of the capture driver.

cbVer

Length, in bytes, of the buffer pointed to by lpszVer.

Return Values

Returns TRUE if successful or FALSE otherwise.

Remarks

If the information description is longer than its buffer, the description is truncated. The returned string is always null-terminated. If a buffer size is zero, its corresponding description is not copied.

Requirements

Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Vfw.h.
Library: Use Vfw32.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT/2000/XP.


What was happening when you'd call the method is that lpszName and lpszVer would always be returned as empty strings, but the return value of the function was true.

Can anyone spot the bug? It took me a while to track it down, but eventually I found it and fixed it. I'll let everyone ponder and discuss the problem. If someone gets it right, I'll be sure to say so -- and if no one gets it right (which I doubt will happen), I'll post the answer in a few days.

13 Comments

Do the Declare statements need to have the lpsz parameters declared ByRef? Just a wild guess.

Is this a BOOL versus Boolean thing?

Are you recoding what I sent you to capture data from WebCam? :P

I don't have the code at hand to look...but it seems familiar.

In the capGetDriverDescription() function, you are missing a comma for the last element of the first declare (capGetDriverDescriptionW). So unless this was just an error when you added it to WordPress, that is my answer.

Phil, I doubt that's the bug here; it's way too obvious, as that would generate a simple syntax error. Aaron noted that it compiled.

Okay, we all give up. What's the answer? :-)

@Anthony -- yes, I reworked your code, and this came up while doing it. :-)

@Phil -- that was probably WordPress eating a character or a simple typo.

I said I'd give ya'll a few days to think about it. The guesses are good, but none of them are correct. I'll give you the answer tomorrow. :-)

OK, cool. Just wanted to make sure I wasn't losing my mind. I wrote that little tidbit before I really understood RB, and haven't had a chance to go back and recode it.

You are declaring the buffer parameters as strings, which should only be done for const values. Because of the magic type conversions, your memory blocks are turned into strings and then thrown away. Instead, pass them as Ptr.

@Brady -- absolutely correct! Congrats, you are teh winnar! :-)

When should I expect my prize? I can send my shipping address along ... :)

@Brady -- I'll buy you a beer at the next RW (assuming you remind me -- I'm pretty forgetful).

[...] Time for another brain flexing bug hunt! This one pertains to declares again, only instead of the code sorta kinda working, it simply causes a crash. Oooh! [...]

Leave a comment

Disclaimer

I'm currently an employee of REAL Software. My blog is mine. The opinions represented in this blog are mine as well and may not represent my employer's opinions. All original material is copyrighted and property of the author.

REALbasic® is a registered trademark of REAL Software, Inc. REAL SQL Server™ and Lingua™ are pending trademarks of REAL Software, Inc. All rights reserved.