I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…
You usually run into the problem that the header files include other header files and you get this long dependency chain where somewhere in the chain some type is not recognized by the converter, to solve this the best is to cherry-pick the dependent types from the included header files and just put everything into one big flat header before passing into the tool. Macros can also be a PITA that you have to rewrite into functions and constants before generating.
You also have http://pinvoke.net/ with almost all win32 functions wrapped already. Same there though, review before use because it's a wiki and the quality is varying.