2017-04-17 22 views
2

我正在尝试调用Rust的Win32 API CertOpenSystemsStoreWCertCloseStore函数。当我这样做时,我在CertCloseStore上遇到访问冲突,所以我想我在某些参数类型上的大小错误,但我看不到它。CertOpenSystemsStoreW或CertCloseStore的Rust FFI声明有什么问题?

下面的Python代码的工作(我有相当的工作C++,但不是很好的包含):

In [1]: import ctypes  
In [2]: c32 = ctypes.windll.crypt32  
In [3]: c32.CertOpenSystemStoreW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p]  
In [4]: c32.CertOpenSystemStoreW.restype = ctypes.c_void_p  
In [5]: c32.CertCloseStore.argtypes=[ctypes.c_void_p, ctypes.c_ulong]  
In [6]: s = c32.CertOpenSystemStoreW(0, "my")  
In [7]: c32.CertCloseStore(s, 0) 
Out[7]: 1 

这里是失败的防锈:

extern crate libc; 
use libc::{c_ulong, c_int, c_void}; 
use std::ffi::OsStr; 
use std::os::windows::ffi::OsStrExt; 
use std::ptr::null; 

type HPROVIDER = c_void; 
type HCERTSTORE = c_void; 
type BOOL = c_int; 

#[link(name = "Crypt32")] 
extern "stdcall" { 
    fn CertOpenSystemStoreW(
     hProv: *const HPROVIDER, szSubsystemProtocol: *const u16) -> HCERTSTORE; 
    fn CertCloseStore(
     hCertStore: HCERTSTORE, dwFlags: c_ulong) -> BOOL; 
} 

fn to_utf16(s: &str) -> Vec<u16> { 
    let os_s = OsStr::new(s); 
    return os_s.encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>(); 
} 

fn main() { 
    let protocol_utf16 = to_utf16("my"); 
    let storehandle; 
    unsafe { 
     storehandle = CertOpenSystemStoreW(null(), protocol_utf16.as_ptr()); 
    } 

    let freeresults; 
    unsafe { 
     freeresults = CertCloseStore(storehandle, 0); 
    } 
    println!("{}", freeresults); 
} 

我使用防锈1.16。

回答

1

嘛,有两个问题:

  1. DWORD值是32位的,不管你是在64位或32位Windows(这是有道理的,我想)。所以我的CertCloseStore的第二个参数是错误的。
  2. c_void不是指针类型 - 它只是一个u8。所以我上面的代码应该是这样的type HPROVIDER = *const c_void;(这不是很好,因为它使所有HPROVIDER常量,但我没有看到一种方法来做一个Rust风格的指针typedef没有指定'mut'或'const') 。
+0

#1真的是真的吗?与其他操作系统中的常识和惯例相反,在Windows C编译器上,“unsigned long”实际上是32位的。 – user4815162342

+0

@ user4815162342:是的,'DWORD'总是32位大小,请参见[Windows数据类型](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx):“ * A ** 32位**无符号整数,范围为0到4294967295十进制*“64位版本为DWORDLONG,平台相关版本为DWORD_PTR。 –

+0

@RemyLebeau是的,但'unsigned long'也是32位大小(在Windows上),所以'CertCloseStore'的签名实际上是正确的。 OP还报告使用'ctypes.c_ulong'工作的Python代码,这与此一致。 – user4815162342