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

Winapi 调用系统插件后从struct获取信息,winapi,nsis,Winapi,Nsis,我正试图通过系统插件和netapi32库从windows获取一些信息 在分配了一个适合作为WKSTA\u INFO\u 100的结构之后,我尝试调用NetWkstaGetInfo() NetWkstaGetInfo()原型在MSDN中表示: NET\u API\u状态netkstagetinfo( _在ulpwstr servername中, _在德沃德级别, _输出字节*bufptr ); 而WKSTA\u INFO\u 100是 typedef结构\u WKSTA\u信息\u 100{ D

我正试图通过系统插件和netapi32库从windows获取一些信息

在分配了一个适合作为
WKSTA\u INFO\u 100
的结构之后,我尝试调用
NetWkstaGetInfo()

NetWkstaGetInfo()
原型在MSDN中表示:

NET\u API\u状态netkstagetinfo(
_在ulpwstr servername中,
_在德沃德级别,
_输出字节*bufptr
);
WKSTA\u INFO\u 100

typedef结构\u WKSTA\u信息\u 100{
DWORD wki100_平台id;
LMSTR wki100_计算机名称;
LMSTR wki100_langroup;
德沃德wki100大学本科;
德沃德wki100小调;
}西九龙文娱艺术区资讯100、*西九龙文娱艺术区资讯100、*西九龙文娱艺术区资讯100;
对于初步测试,我尝试在messagebox中显示结构成员。我首先用伪信息初始化结构,以检查api调用是否替换了分配块的内容

但是直到现在,在第一个struct成员之后,我几乎什么也没有得到,我假设struct没有正确定义,或者我有一个struct对齐问题。不幸的是,奇怪的系统插件文档让我抓狂,对我帮助不大

以下是我的测试脚本:

outfile“hello.exe”
部分
系统::调用/名词加载“*(*i11,t'some',t'thing',i22,i44)i.r0”
Dumpstate::调试
系统::调用/加载“netapi32::NetWkstaGetInfo(i0、i100、ir0)i.r6”
Dumpstate::调试
系统::调用/名词加载“*$0(*i.r1、t.r2、t.r3、i.r4、i.r5)”
Dumpstate::调试
messagebox MB_OK“您好,到$2$3域名(赢取$1-$4.$5)!”
系统::免费$0
分段结束
第一个检索到的值(500)是正确的。但其他成员保留其初始值。我错过了什么

(编辑)推论问题:

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

bufptr为out,因此将r0作为输入传递给NetWkstaGetInfo是没有意义的,该函数不需要输入数据。 您不应该将
*i
与NetApiBufferFree一起使用,
i
单独使用就足够了($0已经有了地址,您不希望系统插件玩指针,只需将它直接传递给API即可)

在前面的示例中,我对bufptr参数使用了
*I 0 r0
,以便在函数启动之前$0为NULL(如果不想使用此技巧,可以在系统调用之前执行
StrCpy$0
)。如果不这样做,则不清楚函数失败时会发生什么。文档没有指定函数失败时bufptr会发生什么,希望将其设置为NULL,但您无法确定。如果函数失败,我们最终会将NULL传递给NetApiBufferFree,这通常是传递给自由函数的安全方法,但文档并没有将其称为OK。为了超级安全起见,您应该只释放一个非空指针:

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
System::调用“netapi32::NetWkstaGetInfo(i0,i100,*i0 r0)i.r1”
${If}0=$1
系统::调用“*$0(i.r1、w.r2、w.r3、i.r4、i.r5)”
DetailPrint“您好,到$2$3域名(赢取$1-$4.$5)!”
${EndIf}
${IfThen}$0${{|}系统::调用“netapi32::NetApiBufferFree(ir0)”${
分段结束


/使用系统插件时不再需要加载(从v2.42开始)./NOUNLOAD阻止NSIS卸载插件。如果插件具有内部状态,这一点很重要,但在您的情况下,唯一的状态是Windows分配的内存块。

感谢您的详细解释!稍后请注意:从结构中获取widechar字符串的正确表示法是
&w${NSIS\U MAX\U STRLEN}.r3
而不是
w.r3
(导致访问冲突)请参阅
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