retep998 / winapi-rs

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

Shell extensions? #1041

Open duckfromdiscord opened 1 year ago

duckfromdiscord commented 1 year ago

This is my first time working w/ the Windows API so bear with me.

Is there a way to make a shell extension in winapi? I want to use IPropertyStore::SetValue to add info to the Details pane when you try to view a certain type of file's properties.

It looks like winapi isn't being maintained very much anymore but I thought I would ask.

sollyucko commented 1 year ago

What exactly are you asking? That function does exist: https://docs.rs/winapi/latest/winapi/um/propsys/struct.IPropertyStore.html#method.SetValue

duckfromdiscord commented 1 year ago

What exactly are you asking? That function does exist: https://docs.rs/winapi/latest/winapi/um/propsys/struct.IPropertyStore.html#method.SetValue

@sollyucko Thank you for the quick response :) I'm asking how to make a shell extension that will register this function and allow me to call it. I think I have to make a dll and then register it. What I want to know is how to make that dll in Rust. Do I need to write a DllMain? Where do I go from there?

duckfromdiscord commented 1 year ago

I will try to explain better. I want to create a shell extension, with just Rust, that will let me modify how Windows Explorer deals with reading details from a certain file type. But the issue is I don't know how to make something like that.

sollyucko commented 1 year ago

You can use crate-type=cdylib to generate a C-compatible DLL: https://doc.rust-lang.org/reference/linkage.html

duckfromdiscord commented 1 year ago

Awesome :) now what functions do I add here to make it work with the shell? DllMain perhaps? And how do I implement the interface

sollyucko commented 1 year ago

Yeah, I guess so. I'm not very familiar with this, but I think these resources should help you get started:

duckfromdiscord commented 1 year ago

This is good. Thank you. I'll let you know how it goes

duckfromdiscord commented 1 year ago

@sollyucko How to implement IClassFactory? https://www.tecgraf.puc-rio.br/iup/examples/shell_extensions/ClassFactory.cpp They did it here. I have to implement https://docs.rs/winapi/latest/winapi/um/unknwnbase/struct.IClassFactory.html somehow

sollyucko commented 1 year ago

I'm not sure. Maybe use RIDL! somehow?

duckfromdiscord commented 1 year ago

I'm gonna use https://raw.githubusercontent.com/GabrielMajeri/com-impl-rs for now. So I have to Rewrite-it-in-Rust for everything in that example you sent?

duckfromdiscord commented 1 year ago

I've started to remake all of it. I'm not sure it'll work because the macro doesn't tell me whether I'm using the correct function signatures or not. I may miss a *mut or a * or a ** somewhere.

duckfromdiscord commented 1 year ago

I will post my progress at https://github.com/duckfromdiscord/midi-windows-ext periodically.

for RegCreateKeyExW, if phkResult is an out, why does it ask me to initialize it?

error[E0381]: used binding `hKey` isn't initialized
  --> src\reg.rs:28:47
   |
20 |     let mut hKey: *mut HKEY;
   |         -------- binding declared here but left uninitialized
...
28 |          KEY_WRITE, &mut security_attributes, hKey, 0 as *mut u32).try_into().unwrap());
   |                                               ^^^^ `hKey` used here but it isn't initialized
   |
help: consider assigning a value
   |
20 |     let mut hKey: *mut HKEY = todo!();
   |    
sollyucko commented 1 year ago

So I have to Rewrite-it-in-Rust for everything in that example you sent?

Yeah, probably, unless you want to deal with C++ FFI.

I may miss a *mut or a * or a ** somewhere.

Just keep in mind that P or LP means *mut and PC or LPC means *const, and you should be fine, I think.

for RegCreateKeyExW, if phkResult is an out, why does it ask me to initialize it?

You're trying to directly read the value of an uninitialized variable. Assuming you're trying to have the handle end up directly in hKey, not in what in points to, do one of the following:

duckfromdiscord commented 1 year ago

Thank you very much.

duckfromdiscord commented 1 year ago

We don't have StringCchPrintf

sollyucko commented 1 year ago

winapi does have w(v)sprintf(A/W); can you use that instead? The buffer has a fixed length of 1024 bytes though...

libc::snprintf is probably a much better option.

format!/write! is another option, but that has different format string syntax and output semantics.

I think the String... functions are only defined in strsafe.h, not in any built-in object files, but you could write a bit of C code to generate an object file with them, then write custom bindings to link it to your Rust code.

duckfromdiscord commented 1 year ago

Yeah, I guess so. I'm not very familiar with this, but I think these resources should help you get started:

* Well-commented example C++ source code: https://www.tecgraf.puc-rio.br/iup/examples/shell_extensions/ (start with dllmain.cpp)

* "Initializing Shell Extension Handlers": https://learn.microsoft.com/en-us/windows/win32/shell/int-shell-exts

Looks like somehow, between the last time I was looking at this code 3 weeks ago, and today, they privated all the code.