[plt-scheme] String as output parameter of FFI call to W32 API GetLogicalDriveStringsW?

From: Chognkai Zhu (czhu at cs.utah.edu)
Date: Mon Feb 1 21:17:26 EST 2010

Use (_ptr o _string) to do that.

Chongkai


Andrea Girotto wrote:
> Hello,
> I have a problem calling via FFI a Windows API function:
> GetLogicalDrivesStringsW.
>
> First of all, if I write:
>
> #lang scheme
> (require scheme/foreign)
> (unsafe!)
>
> (define kernel32 (ffi-lib "kernel32"))
>
> (define get-logical-drive
>   (get-ffi-obj "GetLogicalDrives" kernel32
>                (_fun #:abi 'stdcall -> _uint32)
>                (lambda () (error 'kernel32 "Missing GetLogicalDrives")) ) )
>
> (let ((drives (get-logical-drive)))
>    (display drives)
>    (display #\tab)
>    (display (number->string drives 2))(newline) )
>
> the answer is:
>
> 262157  1000000000000001101
>
> So it is telling me that there are A:, C:, D: and S: (and FFI is
> working! :-)). That's correct, and I have the same answer with:
>
>   
>> (display (filesystem-root-list))(newline)
>>     
> (C:\ D:\ S:\)
>
> (the disk A: is missing because, in my opinion, the
> "filesystem_root_list" function in src/mzscheme/src/file.c is checking
> it with the "GetDiskFreeSpace" and there's absolutely no floppy in the
> system...).
>
> Now I need to get the same information in another way (...long story:
> at the end of this path I will enumerate the USB sticks connected to
> the computer, that is a relatively simple task with Linux, but such an
> incredible complex task with Windows API, maybe it's only me and my
> inexperience with Windows...):
>
> (define get-logical-drive-strings-w
>   (get-ffi-obj "GetLogicalDriveStringsW" kernel32
>                (_fun #:abi 'stdcall
>                      _uint32
>                      _string
>                      -> _uint32)
>                (lambda () (error 'kernel32 "Missing
> GetLogicalDriveStrings")) ) )
>
> (define get-logical-drive-strings
>   (let* ((n 128)
> 	 (s (make-string n #\~)))
>     (display (get-logical-drive-strings-w 128 s))(newline)
>     (display s)(newline)
>     (display (string->list s))(newline) ) )
>
> I'm filling 128 chars with the "~" character before calling the
> GetLogicalDriveStringsW.
> This Windows API should return the number of characters written in the
> string. Instead, the answer is:
>
> 16
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> (~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
>  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
>  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
>  ~ ~ ~ ~ ~ ~ ~ ~)
>
> The "16" number is the GetLogicaDriveStringsW that it is telling me
> having written 16 characters...
> But in the string there is only the sequence of "~" that I used to
> initialize it...
>
> My suspect :-) is that I cannot call a FFI function using a Scheme
> string as output parameter.
>
> BTW: the "filesystem_root_list" function in src/mzscheme/src/file.c is
> calling "GetLogicalDriveStrings" to list the filesystems' roots. I
> think that "GetLogicalDriveStrings" is a C/C++ macro of
> "GetLogicalDriveStringsW" or "GetLogicalDriveStringsA", because the
> first one is triggering the error message of "get-ffi-obj", the others
> two are not...
>
> So how can I pass a string as output parameter (to be filled from
> GetLogicalDriveStringsW) and read it back?
>
> Thank you,
> Best regards,
> Andrew.
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>   



Posted on the users mailing list.