Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Questions about @winapi/@capi

May
3,515
5
1/ When the BUFFER keyword is used (so TCC would provide a buffer in which the function can return a string),
- is it necessary to specify the size of the buffer, or does TCC automatically provide it to the called function?
- if the buffer size must be specified in the TCC command using @WINAPI, what is the maximum size?

2/ Some APIs fill the buffer with data structured in the manner of environment variable storage, i.e., multiple individual strings, each terminated with a NUL character, with an empty string representing the end of the list. TCC users can only access the first string of the result, because its NUL terminator cuts off access. How can we access the subsequent strings? Possible methods I see:
- spread the results into an array (undoubtedly requires significant TCC enhancement)
- put the result into a binary buffer. This might be possible by passing the address and size of an already allocated binary buffer to the API, but I cannot find TCC syntax to make this possible.

BTW, the HELP lines displaying the syntax of @CAPI and of @WINAPI have an unmatched left bracket [ where the choices of parameter formats to be passed to the API are shown, the list of choices is not closed, and there is no indication of repeatability. It apparently assumes that only professional programmers will try to use these functions and their mental parsers are DWIM.
 
1/ When the BUFFER keyword is used (so TCC would provide a buffer in which the function can return a string),
- is it necessary to specify the size of the buffer, or does TCC automatically provide it to the called function?
- if the buffer size must be specified in the TCC command using @WINAPI, what is the maximum size?

2/ Some APIs fill the buffer with data structured in the manner of environment variable storage, i.e., multiple individual strings, each terminated with a NUL character, with an empty string representing the end of the list. TCC users can only access the first string of the result, because its NUL terminator cuts off access. How can we access the subsequent strings? Possible methods I see:
- spread the results into an array (undoubtedly requires significant TCC enhancement)
- put the result into a binary buffer. This might be possible by passing the address and size of an already allocated binary buffer to the API, but I cannot find TCC syntax to make this possible.

1. No, TCC does not require you to specify the buffer size though the API you're calling may require it (often does) as one of it's arguments. Everything after @WINAPI's "function" should be arguments to that function. [Rex, how big a buffer is passed?]

... don't know about 2.
 
The QueryDosDevice function is one which requires a buffer where it returns one or more NUL-terminated strings. The "IsSubst" function variants proposed in another thread all used the string literal BUFFER as described in the @WINAPI help for the TCC supplied buffer, and the number 260 as its size. I tried the function without specifying BUFFER's size, and it worked - but I don't know if it might have corrupted some data storage areas, esp. when I used the literal string NULL to indicate that I want a list of ALL devices. However, if BUFFER is at least 260 characters, the longest list would have only 27 elements, the first 26 consisting of a letter, a colon, and a NUL, the last just a NUL, not requiring a buffer bigger than 79 characters, so I don't expect that there would have been an overflow...
 
The QueryDosDevice function is one which requires a buffer where it returns one or more NUL-terminated strings. The "IsSubst" function variants proposed in another thread all used the string literal BUFFER as described in the @WINAPI help for the TCC supplied buffer, and the number 260 as its size. I tried the function without specifying BUFFER's size, and it worked - but I don't know if it might have corrupted some data storage areas, esp. when I used the literal string NULL to indicate that I want a list of ALL devices. However, if BUFFER is at least 260 characters, the longest list would have only 27 elements, the first 26 consisting of a letter, a colon, and a NUL, the last just a NUL, not requiring a buffer bigger than 79 characters, so I don't expect that there would have been an overflow...

I used 260 out of habit ... because that's "MAX_PATH" and I figured it would be good enough. Seeing that QDD() returns paths in the "\??\" format, I suppose it's possible that MAX_PATH might not be enough (because paths in that format can be huge). I suspect the buffer TCC actually supplies is much bigger than that (TCC uses huge buffers for almost everything). In any event, APIs that ask for a buffer size are smart enough not to write past that point so there won't be corruption unless you specify a buffer size larger than TCC actually provides (which, as I said, is probably pretty big).
 
The QueryDosDevice function is one which requires a buffer where it returns one or more NUL-terminated strings. The "IsSubst" function variants proposed in another thread all used the string literal BUFFER as described in the @WINAPI help for the TCC supplied buffer, and the number 260 as its size. I tried the function without specifying BUFFER's size, and it worked - but I don't know if it might have corrupted some data storage areas, esp. when I used the literal string NULL to indicate that I want a list of ALL devices. However, if BUFFER is at least 260 characters, the longest list would have only 27 elements, the first 26 consisting of a letter, a colon, and a NUL, the last just a NUL, not requiring a buffer bigger than 79 characters, so I don't expect that there would have been an overflow...
Since QDD requires size as one of its arguments, I suspect that the API ended up using whatever happened to be on the stack at that location. Which was probably a huge number (return address perhaps?). But as long as the actual output is smaller than the true buffer size, you'd never have noticed.
 
1/ When the BUFFER keyword is used (so TCC would provide a buffer in which the function can return a string),
- is it necessary to specify the size of the buffer, or does TCC automatically provide it to the called function?

No. TCC uses a buffer size equivalent to the maximum argument size.

2/ Some APIs fill the buffer with data structured in the manner of environment variable storage, i.e., multiple individual strings, each terminated with a NUL character, with an empty string representing the end of the list. TCC users can only access the first string of the result, because its NUL terminator cuts off access. How can we access the subsequent strings?

You cannot. (And nobody's ever asked for it.)

It apparently assumes that only professional programmers will try to use these functions and their mental parsers are DWIM.

Nobody but professional programmers should be using @WINAPI / @CAPI. There are at least a couple dozen Windows APIs that will cheerfully obliterate your entire system with a single bad argument. (It would be safer for me to mail every user a grenade and hope that they're smart enough not to pull the pin and stuff it in their shorts, than to encourage widespread use of @WINAPI.)
 
2/ Some APIs fill the buffer with data structured in the manner of environment variable storage, i.e., multiple individual strings, each terminated with a NUL character, with an empty string representing the end of the list. TCC users can only access the first string of the result, because its NUL terminator cuts off access. How can we access the subsequent strings?

You cannot. (And nobody's ever asked for it.)

I know I did not previously ask for it because I was always going through TCC features to obtain all information, without tunneling through to Windows internals. Now that I have become interested, and I realize some APIs return information is such awkward manner, I am asking a means to overcome this limitation. As far as I can tell allowing the name and size of an allocated binary buffer to be passed to the API through the @WINAPI/@CAPI call would be a 100% backward compatible enhancement, and my guess is would not tax the parser too much, e.g., a new keyword in place of BUFFER, BINARYBUFFER=handle would do the job.
 
I know I did not previously ask for it because I was always going through TCC features to obtain all information, without tunneling through to Windows internals. Now that I have become interested, and I realize some APIs return information is such awkward manner, I am asking a means to overcome this limitation.

Hello Steve,
Are you looking to do something similar to what AutoHotKey does? (DllCall, VarSetCapacity, RegisterCallback)

Joe
 

Similar threads

Back
Top