微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从 NSIS 中的 RCData 资源读取字符串

如何解决如何从 NSIS 中的 RCData 资源读取字符串

我在 RCData 资源中有一个 ANSI 字符串,我想将该字符串存储在一个变量中。我已经到了可以获取资源指针和数据大小的地步了:

; HMODULE GetModuleHandle(LPCSTR lpModuleName);
System::Call "kernel32::GetModuleHandle(i 0) i.r0"

; HRSRC FindResource(HMODULE hModule,LPCSTR lpName,LPCSTR lpType);
System::Call "kernel32::FindResource(i 0,t 'DATA',i 10) i.r1"

; HGLOBAL LoadResource(HMODULE hModule,HRSRC hResInfo);
System::Call "kernel32::LoadResource(i r0,p r1) i.r2"

; LPVOID LockResource(HGLOBAL hResData);
System::Call "kernel32::LockResource(i r2) p.r3"

; DWORD SizeofResource(HMODULE hModule,HRSRC hResInfo);
System::Call "kernel32::SizeofResource(i r0,i r1) i.r4"

现在我不太确定该怎么做。我对 NSIS 很陌生,我认为我的问题是我并不真正了解变量在 NSIS 中的工作方式以及当变量用作不同类型的系统调用输出时会发生什么(它具有什么值)。 (我认为)我需要的是将 $4 字节从存储在 $3 中的地址复制到新缓冲区,并(可能?)用零终止它。我认为这样的事情可以工作:

System::Alloc ${NSIS_MAX_STRLEN}
Pop $5
System::copy /$4 $5 $3

但事实并非如此。经过一些实验,我明白了这一点:

System::Call "*$3(&m$4.r5)"

但我真的不知道为什么这会起作用,如果这是处理此任务的正确方式以及为什么上面的复制版本不起作用。

解决方法

在 System::Copy 代码中,$5 包含分配的缓冲区的内存地址(作为字符串,好像有人做了 sprintf(reg5,"%i",address))。如果您执行 MessageBox mb_ok $5,您只会看到此地址。但是,如果您执行 System::Call user32::MessageBoxA(p0,pr5,p0,i0),您应该会看到您的字符串。

System::Call 代码使用您指定的类型转换源和/或目标。这是一种完全有效的方法,而且比复制代码的工作量少。

如果我们有一些需要类型转换的东西,而不是在您的特定情况下基本上是字节副本,这可能更容易形象化。

想象一下,如果我们有 C 语言

typedef struct { int foo,bar; } MyS;
MyS*ptr = allocandfill();

在 NSIS 中,$1 是 ptr 的值:

System::Call '*$1(i.r2,i1234)'

我们经常将其称为 System struct 语法,* 可以被认为是取消引用从 $1 开始的内存,并将内存解释为基于我们指定的类型的结构。

在我这里的具体示例中,我们说第一个成员是 int,我不想更改值/源(点),但我希望将当前值作为输出存储在 r2 ($2) 中。这将基本上执行 itoa,其中 $2 是目的地。第二个成员是另一个 int,我用数字 1234 覆盖其当前值。在 C 中,这将执行 ptr->bar = atoi("1234")

完成任务的第三种方法是调用 Windows 函数并让它完成工作:

System::Call `kernel32::lstrcpyA(m.r5,pr3)' ; or lstrcpynA if the string is not zero-terminated or you want to chop it to n characters

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。