NSIS 中调用内核函数的基本理解

Basic understanding of calling kernel functions in NSIS

在 NSIS 中,我经历了一些 API,它调用了 Windows 的一些函数。

例如:

  1. Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0

  2. Kernel32::GetLocaleInfo(i,i,t,i)i(2048,0x2,.r0,${NSIS_MAX_STRLEN})i

由于我是新手,谁能解释一下这里发生了什么?什么是 ti.ro 等等?

我知道kernel32是一个DLL,SetEnvironmentVariable & GetLocaleInfo是这个DLL中定义的函数。

The documentation 会告诉你 ti 是什么。

System::Call 的基本语法是 module::function(parameters)return。参数和 return 是可选的,它们都遵循相同的基本格式:类型输入输出。如果您需要输入 and/or 输出,则类型不是可选的。

参数和 return 可以重复多次,这仅在函数原型作为定义存在时才有用,但有时您也会在 NSIS Wiki 上看到这种语法。 Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0Kernel32::SetEnvironmentVariable(t "VAR1", t "$R0")i.r0 完全相同。使用定义时,它看起来像这样:

!define SetEnvironmentVariable "Kernel32::SetEnvironmentVariable(t, t)i"
System::Call '${SetEnvironmentVariable}("VAR1", "$R0").r0'

如果您了解 C/C++ 或 Delphi 等语言,在使用系统插件时会很有帮助,因为您需要了解基本的 Windows 类型及其功能通常使用。

例如,如果您想调用 GetWindowsDirectory 函数,您首先要 look at the function on MSDN:

UINT WINAPI GetWindowsDirectory(_Out_ LPTSTR lpBuffer, _In_ UINT uSize);

将其转换为 NSIS 可为您提供 Kernel32::GetWindowsDirectory(t, i)i 的初始框架(WINAPI 是默认调用约定)。 t 映射到 Windows TCHAR* 类型, i 是一个 32 位整数,与 ULONG, LONG, [=25] 相同=]、INTUINTINT32UINT32 在 Windows SDK 中。 唯一缺少的部分是输入和输出。 MSDN 声明用 SAL 注释修饰,因此很容易看出哪些参数是输入的,哪些是输出的。

一个工作示例可能如下所示:

System::Call 'Kernel32::GetWindowsDirectory(t .r1, i ${NSIS_MAX_STRLEN})i .r0'
DetailPrint "Return=[=12=] Output1="

.可以在没有输入的时候作为"nothing"的占位符。在这种情况下,我们使用它两次。使用 System::Call 时 return 值永远不会有输入,我们还有一个仅输出参数。

r1r0</code> 和 <code>[=34=] NSIS 寄存器的别名,当您需要输出某些内容时必须使用这些别名。普通的 NSIS 寄存器可以用作输入,但变量扩展发生在 NSIS 内部而不是插件中,这可能会导致字符串中的引号出现问题,如果字符串可能包含引号或合法的系统插件,则不推荐使用句法。因此,我建议将您的第一个示例重写为 Kernel32::SetEnvironmentVariable(t "VAR1", t R0)i.r0.

在 C 中你的第二个例子看起来像

char mybuf[1024];
GetLocaleInfo(MAKELCID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), LOCALE_SLANGUAGE, mybuf, sizeof(mybuf));