Skip to content

Commit

Permalink
Linux: util: BSTR contains a wide string instead of UTF-8
Browse files Browse the repository at this point in the history
Resulting strings were only one character long because the second byte
for ASCII text is NULL.

On Linux DXC properly uses wchar_t which is 32-bit instead of 16-bit.

Fixes: 94fbad7 ("Support libdxcompiler.so on Linux (#5)")
  • Loading branch information
MarijnS95 committed Nov 10, 2020
1 parent aeba1b6 commit f1ad454
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
14 changes: 14 additions & 0 deletions examples/intellisense-tu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn main() {

let name = cursor.get_display_name().unwrap();
println!("Name {:?}", name);
assert_eq!(name, "copy.hlsl");

let cursor_kind = cursor.get_kind().unwrap();
println!("CursorKind {:?}", cursor_kind);
Expand All @@ -42,6 +43,19 @@ fn main() {

let child_cursors = cursor.get_all_children().unwrap();

assert_eq!(
child_cursors[0].get_display_name(),
Ok("g_input".to_owned())
);
assert_eq!(
child_cursors[1].get_display_name(),
Ok("g_output".to_owned())
);
assert_eq!(
child_cursors[2].get_display_name(),
Ok("copyCs(uint3)".to_owned())
);

for child_cursor in child_cursors {
let range = child_cursor.get_extent().unwrap();
println!("Child Range {:?}", range);
Expand Down
23 changes: 15 additions & 8 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,34 @@ pub(crate) fn from_wide(wide: LPWSTR) -> String {
unsafe {
widestring::WideCStr::from_ptr_str(wide)
.to_string()
.expect("utf16 decode failed")
.expect("widestring decode failed")
}
}

#[cfg(windows)]
pub(crate) fn from_bstr(string: BSTR) -> String {
unsafe {
let len = SysStringLen(string);
let slice: &[WCHAR] = ::std::slice::from_raw_parts(string, len as usize);
let result = String::from_utf16(slice).unwrap();
let len = SysStringLen(string) as usize;

let result = widestring::WideCStr::from_ptr_with_nul(string, len)
.to_string()
.expect("widestring decode failed");

SysFreeString(string);
result
}
}

#[cfg(not(windows))]
pub(crate) fn from_bstr(string: BSTR) -> String {
// TODO (Marijn): This does NOT cover embedded NULLs:
// https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-sysstringlen#remarks
// Fortunately BSTRs are only used in names currently, which _likely_ don't include NULL characters (like binary data)
let result = from_lpstr(string as LPSTR);
// TODO (Marijn): This does NOT cover embedded NULLs

// BSTR contains its size in the four bytes preceding the pointer, in order to contain NULL bytes:
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/bstr
// DXC on non-Windows does not adhere to that and simply allocates a buffer without prepending the size:
// https://github.com/microsoft/DirectXShaderCompiler/blob/a8d9780046cb64a1cea842fa6fc28a250e3e2c09/include/dxc/Support/WinAdapter.h#L49-L50
let result = from_wide(string as LPWSTR);

unsafe { SysFreeString(string) };
result
}
Expand Down

0 comments on commit f1ad454

Please sign in to comment.