Home > Enterprise >  How can I convert LPWSTR into &str
How can I convert LPWSTR into &str

Time:10-04

In my previous question I asked how to cast LPVOID to LPNETRESOURCEW. And it goes well. I have a struct of NETRESOURCEW with fields:

    dwScope: DWORD,
    dwType: DWORD,
    dwDisplayType: DWORD,
    dwUsage: DWORD,
    lpLocalName: LPWSTR,
    lpRemoteName: LPWSTR,
    lpComment: LPWSTR,
    lpProvider: LPWSTR,

According to docs nr.lpRemoteName is LPWSTR -> *mut u16. I've tried using OsString::from_wide but nothing got well. How can I convert LPWSTR into Rust *str or String and print it in console?

CodePudding user response:

This is normally done by marshalling the string pointer into a slice. First you need to get the length of the string / slice which can be done like this if the string is null-terminated:

let length = (0..).take_while(|&i| *my_string.offset(i) != 0).count();

Then you can create the slice like so

let slice = std::slice::from_raw_parts(my_string, length);

and finally convert the slice into an OsString:

let my_rust_string = OsString::from_wide(slice).to_string_lossy().into_owned();

Update due to comment

I have verified that the given approach works as can be reproduced using this snippet:

use std::{ffi::OsString, os::windows::prelude::OsStringExt};

use windows_sys::w;

fn main() {
    let my_string = w!("This is a UTF-16 string.");

    let slice;
    unsafe {
        let length = (0..).take_while(|&i| *my_string.offset(i) != 0).count();
        slice = std::slice::from_raw_parts(my_string, length);
    }

    let my_rust_string = OsString::from_wide(slice).to_string_lossy().into_owned();
    println!("{}", my_rust_string);
}

If you get a STATUS_ACCESS_VIOLATION it is most likely because your string is not null-terminated in which case you would need to determine the length of the string in another way or preallocate the buffer.

  • Related