nsis_plugin/raw.rs
1//! Raw FFI declarations, transcribed from the NSIS 3.12 sources.
2//!
3//! Everything here is a faithful mirror of `Source/exehead/api.h` and
4//! `Contrib/ExDLL/pluginapi.h`. Field order matters — do not reorder.
5
6use core::ffi::{c_int, c_void};
7
8use crate::tchar::Tchar;
9
10/// Installer's parent window.
11pub type Hwnd = *mut c_void;
12
13/// Module handle of the loaded plug-in DLL.
14pub type Hmodule = *mut c_void;
15
16/// Plug-in ABI version introduced in NSIS 2.42.
17///
18/// Version checks must use `>=`, per the comment in `api.h`.
19pub const NSISPIAPIVER_1_0: c_int = 0x0001_0000;
20
21/// The most recent plug-in ABI version this crate knows about.
22pub const NSISPIAPIVER_CURR: c_int = NSISPIAPIVER_1_0;
23
24/// Last message a plug-in receives: do final cleanup.
25pub const NSPIM_UNLOAD: c_int = 0;
26
27/// Sent after `.onGUIEnd`.
28pub const NSPIM_GUIUNLOAD: c_int = 1;
29
30/// The signature of every plug-in export, as generated by
31/// [`nsis_fn!`](crate::nsis_fn).
32///
33/// The trailing ellipsis in the C declaration makes the export `cdecl`, not
34/// `stdcall` — the `NSISCALL` helpers in `pluginapi.h` are stdcall, the export
35/// itself is not. Rust's `extern "C"` is cdecl on i686, so this lines up.
36pub type Export =
37 unsafe extern "C" fn(Hwnd, c_int, *mut Tchar, *mut *mut StackNode, *mut ExtraParameters);
38
39/// A plug-in callback registered through [`ExtraParameters::register_plugin_callback`].
40///
41/// `api.h` specifies this is always `__cdecl`, "for future expansion
42/// possibilities" — note that it is *not* `NSISCALL`. Return `0` for unknown
43/// messages.
44pub type NsisPluginCallback = unsafe extern "C" fn(c_int) -> usize;
45
46/// Installer state exposed to plug-ins, mirroring `exec_flags_t`.
47#[repr(C)]
48#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
49pub struct ExecFlags {
50 /// `SetAutoClose`.
51 pub autoclose: c_int,
52 /// `SetShellVarContext`: user context = 0, machine context = 1.
53 pub all_user_var: c_int,
54 /// `IfErrors` / `ClearErrors` / `SetErrors`.
55 pub exec_error: c_int,
56 /// `IfAbort`.
57 pub abort: c_int,
58 /// `IfRebootFlag` / `SetRebootFlag`.
59 pub exec_reboot: c_int,
60 /// Set once a reboot has been requested.
61 pub reboot_called: c_int,
62 /// Deprecated (`XXX_cur_insttype`). Do not use.
63 pub xxx_cur_insttype: c_int,
64 /// Plug-in ABI version. Only meaningful from NSIS 2.42 onward.
65 pub plugin_api_version: c_int,
66 /// `IfSilent` / `SetSilent`.
67 pub silent: c_int,
68 /// `GetInstDirError`.
69 pub instdir_error: c_int,
70 /// `IfRtlLanguage`: 1 when `$LANGUAGE` is a right-to-left language.
71 pub rtl: c_int,
72 /// `SetErrorLevel`.
73 pub errlvl: c_int,
74 /// `SetRegView`: default view = 0, alternative view = `KEY_WOW64_*`.
75 pub alter_reg_view: c_int,
76 /// `SetDetailsPrint`.
77 pub status_update: c_int,
78}
79
80/// The `extra_parameters` block, fifth argument to every plug-in export.
81#[repr(C)]
82pub struct ExtraParameters {
83 /// Pointer to the installer's live [`ExecFlags`].
84 pub exec_flags: *mut ExecFlags,
85 /// Runs a code segment in the installer. Honest passthrough, no wrapper.
86 pub execute_code_segment: Option<unsafe extern "system" fn(c_int, Hwnd) -> c_int>,
87 /// Replaces invalid filename characters in place.
88 pub validate_filename: Option<unsafe extern "system" fn(*mut Tchar)>,
89 /// Registers an unload callback. Returns 0 on success, 1 if already
90 /// registered, and < 0 on error.
91 pub register_plugin_callback:
92 Option<unsafe extern "system" fn(Hmodule, NsisPluginCallback) -> c_int>,
93}
94
95/// A node of the installer's `GlobalAlloc`'d singly linked stack.
96///
97/// `text` is declared as a one-element array in C but is allocated with room
98/// for `string_size` characters. Never construct one by value.
99#[repr(C)]
100pub struct StackNode {
101 /// Next node, or null at the bottom of the stack.
102 pub next: *mut StackNode,
103 /// Start of the NUL-terminated string. Really `[Tchar; string_size]`.
104 pub text: [Tchar; 1],
105}
106
107impl StackNode {
108 /// Byte size of a node able to hold `string_size` characters, matching
109 /// `GlobalAlloc(GPTR, sizeof(stack_t) + g_stringsize * sizeof(TCHAR))`.
110 #[inline]
111 pub const fn alloc_size(string_size: usize) -> usize {
112 core::mem::size_of::<StackNode>() + string_size * core::mem::size_of::<Tchar>()
113 }
114}