eulumdat_windows_preview/
lib.rs1#![cfg(windows)]
28
29mod handler;
30mod registry;
31mod render;
32
33use std::ffi::c_void;
34use windows::core::{implement, Error as WinError, IUnknown, Interface, Result as WinResult, GUID};
35use windows::Win32::Foundation::{
36 BOOL, CLASS_E_CLASSNOTAVAILABLE, E_POINTER, E_UNEXPECTED, HINSTANCE, S_OK,
37};
38
39const DLL_PROCESS_ATTACH: u32 = 1;
40const DLL_PROCESS_DETACH: u32 = 0;
41
42fn debug_log(msg: &str) {
44 use std::io::Write;
45 if let Ok(mut file) = std::fs::OpenOptions::new()
46 .create(true)
47 .append(true)
48 .open("C:\\eulumdat_preview_debug.log")
49 {
50 let timestamp = std::time::SystemTime::now()
51 .duration_since(std::time::UNIX_EPOCH)
52 .map(|d| d.as_secs())
53 .unwrap_or(0);
54 let _ = writeln!(file, "[{}] {}", timestamp, msg);
55 }
56}
57
58#[no_mangle]
60pub unsafe extern "system" fn DllMain(
61 _hinst: HINSTANCE,
62 reason: u32,
63 _reserved: *mut c_void,
64) -> BOOL {
65 match reason {
66 DLL_PROCESS_ATTACH => {
67 debug_log("DllMain: DLL_PROCESS_ATTACH");
68 }
69 DLL_PROCESS_DETACH => {
70 debug_log("DllMain: DLL_PROCESS_DETACH");
71 }
72 _ => {}
73 }
74 BOOL::from(true)
75}
76
77use windows::Win32::System::Com::{IClassFactory, IClassFactory_Impl};
78
79use handler::EulumdatPreviewHandler;
80
81pub const CLSID_EULUMDAT_PREVIEW: GUID = GUID::from_values(
84 0xA1B2C3D4,
85 0xE5F6,
86 0x7890,
87 [0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90],
88);
89
90#[implement(IClassFactory)]
92pub struct EulumdatClassFactory;
93
94impl IClassFactory_Impl for EulumdatClassFactory_Impl {
95 fn CreateInstance(
96 &self,
97 punkouter: Option<&IUnknown>,
98 riid: *const GUID,
99 ppvobject: *mut *mut c_void,
100 ) -> WinResult<()> {
101 debug_log("CreateInstance called");
102
103 if punkouter.is_some() {
105 debug_log("CreateInstance: Aggregation not supported");
106 return Err(WinError::from(
107 windows::Win32::Foundation::CLASS_E_NOAGGREGATION,
108 ));
109 }
110
111 unsafe {
112 if ppvobject.is_null() {
113 debug_log("CreateInstance: Null ppvobject");
114 return Err(WinError::from(E_POINTER));
115 }
116 *ppvobject = std::ptr::null_mut();
117
118 debug_log("CreateInstance: Creating handler...");
119 let handler: IUnknown = EulumdatPreviewHandler::new().into();
120 let result = handler.query(&*riid, ppvobject);
121 debug_log(&format!("CreateInstance: query result = {:?}", result));
122 result.ok()
123 }
124 }
125
126 fn LockServer(&self, _flock: windows::Win32::Foundation::BOOL) -> WinResult<()> {
127 Ok(())
128 }
129}
130
131#[no_mangle]
136pub unsafe extern "system" fn DllGetClassObject(
137 rclsid: *const GUID,
138 riid: *const GUID,
139 ppv: *mut *mut c_void,
140) -> windows::core::HRESULT {
141 debug_log("DllGetClassObject called");
142
143 if ppv.is_null() {
144 debug_log("DllGetClassObject: Null ppv");
145 return E_POINTER;
146 }
147 *ppv = std::ptr::null_mut();
148
149 if *rclsid != CLSID_EULUMDAT_PREVIEW {
150 debug_log("DllGetClassObject: Wrong CLSID");
151 return CLASS_E_CLASSNOTAVAILABLE;
152 }
153
154 debug_log("DllGetClassObject: Creating factory...");
155 let factory: IClassFactory = EulumdatClassFactory.into();
156 let result = factory.query(&*riid, ppv);
157 debug_log(&format!("DllGetClassObject: result = {:?}", result));
158 result
159}
160
161#[no_mangle]
166pub unsafe extern "system" fn DllCanUnloadNow() -> windows::core::HRESULT {
167 S_OK
169}
170
171#[no_mangle]
176pub unsafe extern "system" fn DllRegisterServer() -> windows::core::HRESULT {
177 match registry::register_preview_handler() {
178 Ok(()) => S_OK,
179 Err(e) => {
180 let _ = std::fs::write(
182 "C:\\eulumdat_preview_register_error.txt",
183 format!("Registration failed: {:?}", e),
184 );
185 E_UNEXPECTED
186 }
187 }
188}
189
190#[no_mangle]
195pub unsafe extern "system" fn DllUnregisterServer() -> windows::core::HRESULT {
196 match registry::unregister_preview_handler() {
197 Ok(()) => S_OK,
198 Err(_) => E_UNEXPECTED,
199 }
200}