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