Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

‎Dia::IDiaSourceFile::get_checksum implementation does not work properly #18

Closed
JeromySt opened this issue Mar 26, 2024 · 2 comments · Fixed by #20
Closed

‎Dia::IDiaSourceFile::get_checksum implementation does not work properly #18

JeromySt opened this issue Mar 26, 2024 · 2 comments · Fixed by #20

Comments

@JeromySt
Copy link

JeromySt commented Mar 26, 2024

I am trying to leverage the DIA SDK in rust using this crate (Thank You!).

I have been able to flawlessly use it, except for when I tried to leverage ‎Dia::IDiaSourceFile::get_checksum(...). I was unable to find any variation that allowed that API to work properly.

I ended up using something like:

let mut checksum = Vec::<u8>::new();
unsafe {
    // Get the size of the checksum buffer
    let mut cbdata = 0;
    (windows::core::Interface::vtable(&self.source_file).get_checksum)(
        windows::core::Interface::as_raw(&self.source_file),
        0,
        &mut cbdata,
        std::ptr::null_mut()).unwrap();

    // Create a buffer to hold the checksum
    checksum.resize(cbdata as usize, 0);

    // Retrieve the checksum into the buffer
    (windows::core::Interface::vtable(&self.source_file).get_checksum)(
        windows::core::Interface::as_raw(&self.source_file),
        cbdata,
        &mut cbdata,
        checksum.as_mut_ptr()).unwrap();
}

To workaround the issue.

I saw that this method was implemented by windows-bindgen and I was curious if this is a bug, or if it would be worthwhile to investigate this issue for bindgen?

Thank you again for all of this great work!

@riverar
Copy link
Collaborator

riverar commented Mar 27, 2024

Hey @JeromySt, here's a sample. It's slightly inefficient; it allocates a 256 byte buffer up front, due to get_checksum not accepting a null pbdata. (This is a crate metadata issue, this method parameter isn't marked as [Optional]. I'll get this fixed.)

[package]
name = "sample_checksum"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies.windows]
version = "0.53"

[dependencies.microsoft-dia]
version = "0.10.0"
use microsoft_dia::{nsNone, DiaSource, IDiaDataSource, SymTagCompiland};
use windows::{
    core::*,
    Win32::System::Com::{CoInitializeEx, COINIT_MULTITHREADED},
};

fn main() -> Result<()> {
    unsafe {
        // Initialize COM and DIA
        CoInitializeEx(None, COINIT_MULTITHREADED).ok()?;
        let source: IDiaDataSource = microsoft_dia::helpers::NoRegCoCreate(
            s!(
                r#"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\DIA SDK\bin\amd64\msdia140.dll"#
            ),
            &DiaSource,
        )?;

        // Open session against own symbols
        let executable = std::env::current_exe().unwrap();
        source.loadDataForExe(&HSTRING::from(executable.as_os_str()), None, None)?;
        let session = source.openSession()?;

        // Get compilands
        let symbols =
            session
                .globalScope()?
                .findChildren(SymTagCompiland, None, nsNone.0 as u32)?;

        // Get source files
        for i in 0..symbols.Count()? {
            let symbol = symbols.Item(i as u32)?;
            let files = session.findFile(&symbol, PCWSTR::null(), nsNone.0 as u32)?;

            // Find files with a checksum and print out details
            for j in 0..files.Count()? {
                let file = files.Item(j as u32)?;
                if file.checksumType()? == 0 {
                    continue;
                }

                let mut byte_count = 0u32;
                let mut bytes = vec![0; 256];
                file.get_checksum(&mut byte_count, &mut bytes)?;
                bytes.truncate(byte_count as usize);

                println!("File: {}", file.fileName()?);
                println!(
                    "{:02x}: {}\n",
                    file.checksumType()?,
                    bytes
                        .iter()
                        .map(|b| format!("{:02x}", b).to_string())
                        .collect::<String>()
                );
            }
        }

        Ok(())
    }
}

@JeromySt
Copy link
Author

JeromySt commented Mar 27, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants