Receive unexpected return values when using GetDriveType() on Windows API

Hi,I met some troubles.I tried to check all the drive types on my computer and was using GetDriveType,but I found it weird to return 1 (means DRIVE_UNKNOWN,I suppose) for all letters in the loop. There exists fixed C:\,D:\,E:\,F:\ on my computer. I'm quite unfamiliar with raw pointers in Rust, so I guess there is something wrong the way I'm dealing it. What's wrong in my code?

use std::{thread::sleep,os::windows::ffi::OsStrExt,time::Duration,ffi::{OsString}};

use winapi::um::fileapi::GetDriveTypeW;

fn main(){

    let letters_1=vec![OsString::from("A:\\"),OsString::from("B:\\"),OsString::from("C:\\"),OsString::from("D:\\"),OsString::from("E:\\"),OsString::from("F:\\"),OsString::from("G:\\"),OsString::from("H:\\"),OsString::from("I:\\"),OsString::from("J:\\"),OsString::from("K:\\"),OsString::from("L:\\"),OsString::from("M:\\"),OsString::from("N:\\"),OsString::from("O:\\"),OsString::from("P:\\"),OsString::from("Q:\\"),OsString::from("R:\\"),OsString::from("S:\\"),OsString::from("T:\\"),OsString::from("U:\\"),OsString::from("V:\\"),OsString::from("W:\\"),OsString::from("X:\\"),OsString::from("Y:\\"),OsString::from("Z:\\")];

    let mut letters_2:Vec<*const u16>=vec![];

    for i in letters_1{

        let j:Vec<u16>=i.encode_wide().collect();

        let k:*const u16=j.as_ptr();

        letters_2.push(k);

    }
    let time=Duration::from_secs(3);

    loop{
        sleep(time);
        println!("loop:");
        for i in letters_2.clone(){
            let a = unsafe{GetDriveTypeW(i)};
            println!("{:?},{:?}",i,a);
}}}

Thank you for any thoughts!

I think the problem is here:

for i in letters_1 {
    let j: Vec<u16> = i.encode_wide().collect();
    let k: *const u16 = j.as_ptr();
    letters_2.push(k);
}

In this block the memory owned by j will be freed at the end, leaving k as a dangling pointer. You need to either store the Vecs or use the pointer immediately.

2 Likes

Oh,I think I understand. When j is freed, k in letters_2 is useless.Thank you again,now I'll solve it.

Raw pointers are Copy, so you can use it after you move it (e.g. by passing it to drop). It just passes a copy instead.

You can't use j after dropping that though. And k is just a pointer to j in each loop iteration. (Then j gets dropped at the end of the loop.)

Store the Vec<u16> and do your .as_ptr() conversion when calling the foreign function:

    // Untested, I'm not on Windows

    let mut letters_2 /* : Vec<Vec<u16>> */ = Vec::new();
    for i in letters_1 {
        let j: Vec<_> = i.encode_wide().collect();
        letters_2.push(j);
    }

    let time=Duration::from_secs(3);
    loop {
        sleep(time);
        println!("loop:");
        for i in &letters_2 {
            let a = unsafe{ GetDriveTypeW(i.as_ptr()) };
            println!("{:?},{:?}", i, a);
        }
    }
3 Likes

Oh thanks, that's useful!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.