retep998 / winapi-rs

Rust bindings to Windows API
https://crates.io/crates/winapi
Apache License 2.0
1.85k stars 392 forks source link

STATUS_ACCESS_VIOLATION error when trying to use Direct Sound #1018

Open ryancsh opened 2 years ago

ryancsh commented 2 years ago

Hello,

I've been trying to load and use dsound.dll at runtime and it fails for some reason I don't understand. In the code snippet below, I tried to comment my thought process throughout:

use core::ptr::*;
use winapi::shared::guiddef::*;
use winapi::um::dsound::*;
use winapi::um::libloaderapi::*;
use winapi::um::unknwnbase::*;
use winapi::um::winnt::*;

fn main() {
  unsafe {
    let DirectSoundCreate = {
      // copy the type signature of the original DirectSoundCreate
      type FnDirectSoundCreate = unsafe extern "system" fn(
        pcGuidDevice: LPCGUID,
        ppDS: *mut LPDIRECTSOUND,
        pUnkOuter: LPUNKNOWN,
      ) -> HRESULT;

      // typecheck the above type against type of original function
      let _typecheck: FnDirectSoundCreate = winapi::um::dsound::DirectSoundCreate;
      println!("_typecheck, [{:?}]", &_typecheck as *const _);

      // try load dsound.dll using LoadLibraryA
      let dsound_lib = LoadLibraryA("dsound.dll\0".as_ptr() as *mut _);
      if dsound_lib.is_null() {
        println!("could not load dsound.dll");
        return;
      }
      println!("loaded dsound.dll, [{:?}]", dsound_lib);

      // try get address of DirectSoundCreate()
      let fn_ptr = GetProcAddress(dsound_lib, "DirectSoundCreate\0".as_ptr() as *mut _);
      if fn_ptr as usize == 0 {
        println!("could not load DirectSoundCreate");
        return;
      }
      println!("loaded DirectSoundCreate, [{:?}]", fn_ptr);

      // TOGGLE THIS
      // choose between using the original function vs. the one we just loaded
      // switch this to true and I get a STATUS_ACCESS_VIOLATION later on
      // switch this to false and code runs to the end.
      if false {
        *(fn_ptr as *const FnDirectSoundCreate)
      } else {
        _typecheck
      }
    };
    let mut dsound_obj = null_mut(); // not important

    // try to use our function
    // leads to 0xc0000005, STATUS_ACCESS_VIOLATION if I use the loaded function
    // runs without issues with original winapi::um::dsound::DirectSoundCreate
    println!("calling DirectSoundCreate()");
    if DirectSoundCreate(null(), &mut dsound_obj, null_mut()) != DS_OK {
      println!("cound not create direct sound object");
      return;
    }
    println!("end");
  }
}

With the toggle true, the output is as follows (program crashes on its own):

_typecheck, [0x3642ff648]
loaded dsound.dll, [0x7ffbb45e0000]
loaded DirectSoundCreate, [0x7ffbb45ff450]
calling DirectSoundCreate()
error: process didn't exit successfully: `target\debug\Test2.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

With the toggle false, the output is as follows:

_typecheck, [0x1f3dcff308]
loaded dsound.dll, [0x7ffbb45e0000]
loaded DirectSoundCreate, [0x7ffbb45ff450]
calling DirectSoundCreate()
end

How do I make the loaded version of the function work as well?
Any help would be very much appreciated.