调用系统插件后从struct获取信息

时间:2012-09-10 12:53:58

标签: winapi nsis

我试图通过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)是正确的。但其他成员保持其初始价值。我缺少什么?

(编辑)推论问题:

  • 似乎在文档和MSDN之后,结构的第一个成员应该是i而不是*i但是如果没有*我没有设法获得正确的返回值(Dumpstate插件倾向于显示它作为地址返回)
  • 是插件必需的/NOUNLOAD参数吗?我找到了几个例子,但没有找到确切的原因。我担心分配的结构可能在没有参数的情况下过早释放。你能证实/体弱吗?

2 个答案:

答案 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分配的内存块。