[plt-scheme] String as output parameter of FFI call to W32 API GetLogicalDriveStringsW?
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
>