我试图通过System插件和netapi32
库从Windows获取一些信息。
在分配了适合NetWkstaGetInfo()
的结构后,我尝试调用WKSTA_INFO_100
。
MSDN中的NetWkstaGetInfo()
原型状态:
NET_API_STATUS NetWkstaGetInfo(
_In_ LPWSTR servername,
_In_ DWORD level,
_Out_ LPBYTE *bufptr
);
虽然WKSTA_INFO_100
是
typedef struct _WKSTA_INFO_100 {
DWORD wki100_platform_id;
LMSTR wki100_computername;
LMSTR wki100_langroup;
DWORD wki100_ver_major;
DWORD wki100_ver_minor;
} WKSTA_INFO_100, *PWKSTA_INFO_100, *LPWKSTA_INFO_100;
对于初步测试,我尝试在消息框中显示结构成员。我首先用虚拟信息初始化结构,以检查api调用是否替换了我分配的块的内容。
但是直到现在我在第一个struct成员之后几乎没有任何东西,我想结构没有正确定义,或者我有结构对齐问题。不幸的是,系统插件的奇怪文档让我疯狂对我没什么帮助。
这是我的测试脚本:
outfile "hello.exe"
section
System::Call /NOUNLOAD "*(*i11,t 'some',t 'thing',i22,i44)i .r0"
Dumpstate::debug
System::Call /NOUNLOAD "netapi32::NetWkstaGetInfo(i0, i100, i r0) i.r6"
Dumpstate::debug
System::Call /NOUNLOAD "*$0(*i.r1, t.r2, t.r3, i.r4, i.r5)"
Dumpstate::debug
messagebox MB_OK "Hello, to $2 $3 domain (win $1 - $4.$5) !"
System::Free $0
sectionEnd
第一个检索到的值(500)是正确的。但其他成员保持其初始价值。我缺少什么?
(编辑)推论问题:
i
而不是*i
但是如果没有*
我没有设法获得正确的返回值(Dumpstate插件倾向于显示它作为地址返回)/NOUNLOAD
参数吗?我找到了几个例子,但没有找到确切的原因。我担心分配的结构可能在没有参数的情况下过早释放。你能证实/体弱吗?答案 0 :(得分:0)
似乎在文档和MSDN之后,结构的第一个成员应该是
i
而不是*i
但是如果没有*
我没有设法获得正确的返回值(Dumpstate插件倾向于显示它作为地址返回)
这是该解决方案的线索:我误解了MSDN页面并且最初没有注意到不是结构传递给NetWkstaGetInfo
但地址由api调用修改的NetWkstaGetInfo*
(并且必须在NetApiBufferFree
之后释放。因此正确的脚本是:
outfile "hello.exe"
section
System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i r0 r0) i.r6"
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
messagebox MB_OK "Hello, to $2 $3 domain (win $1 - $4.$5) !"
System::Call "netapi32::NetApiBufferFree(*i r0) i.r6"
sectionEnd
答案 1 :(得分:0)
bufptr只是因为传递r0作为NetWkstaGetInfo的输入是没有意义的,该函数不需要输入数据。
您不应该将*i
与NetApiBufferFree一起使用,仅i
就够了($ 0已经有了地址,您不希望系统插件使用指针,只需将其直接传递给API)< / p>
!include LogicLib.nsh
System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i 0 r0) i.r1"
${If} 0 = $1
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
DetailPrint "Hello, to $2 $3 domain (win $1 - $4.$5) !"
${EndIf}
System::Call "netapi32::NetApiBufferFree(ir0)"
在上面的示例中,我使用*i 0 r0
作为bufptr参数,以便在函数启动之前$ 0为NULL(如果您不想使用此技巧,则可以在系统之前执行StrCpy $0 0
呼叫)。如果你不这样做,那么不清楚如果函数失败会发生什么。该文档没有说明当函数失败时bufptr会发生什么,希望它设置为NULL但你无法确定。如果函数失败,我们最终将NULL传递给NetApiBufferFree,这通常是传递给自由函数的安全的东西,但是文档并没有将其称为OK。要处于超级安全的一面,你应该只释放一个非NULL指针:
System::Call "netapi32::NetWkstaGetInfo(i0, i100, *i 0 r0) i.r1"
${If} 0 = $1
System::Call "*$0(i.r1, w.r2, w.r3, i.r4, i.r5)"
DetailPrint "Hello, to $2 $3 domain (win $1 - $4.$5) !"
${EndIf}
${IfThen} $0 <> 0 ${|} System::Call "netapi32::NetApiBufferFree(ir0)" ${|}
SectionEnd
/ NOUNLOAD(自v2.42开始)。 / NOUNLOAD阻止NSIS卸载插件。如果插件具有内部状态,那么这很重要,但在您的情况下,唯一的状态是Windows分配的内存块。