Skip to main content

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}