测试系统插件返回的字符串时出现意外的 logiclib 行为 [英] unexpected logiclib behavior when testing string returned by system plugin

查看:31
本文介绍了测试系统插件返回的字符串时出现意外的 logiclib 行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用类似于 我认为最好检查函数返回值而不是宽字符字符串指针.我有点困惑,为什么我的 ${If} 0 <>$1 总是失败?在这种情况下,我检查了一个不属于 $1 等于 0 的域的成员的虚拟机.我想那 ${IfThen} 释放内存的测试也是错误的.

这是示例代码:

!include "logiclib.nsh"输出文件hello2.exe"!define DEBUG `System::Call kernel32::OutputDebugString(ts)`部分调用 GetDCName流行 $0消息框 MB_OK "DCName=$0"节结束函数 GetDCName;将域控制器名称压入堆栈(如果没有 dc 则为空字符串)推$0推$1推$2System::Call "netapi32::NetGetDCName(i0, i0, *w 0 r1) i.r2"转储状态::调试${If} 0 <>1 美元${debug} "复制 $1"StrCpy $0 $1${其他}${debug} "复制空字符串"StrCpy $0 ""${endif}${IfThen} $1 <>0 ${|} System::Call "netapi32::NetApiBufferFree(ir1)" ${|}流行 $2流行 $1兑换 $0函数结束

感谢安德斯,这是更正后的函数:

函数 GetDCName;将域控制器名称压入堆栈(如果没有 dc 则为空字符串)推$0推$1推$2System::Call "netapi32::NetGetDCName(i0, i0, *i 0 r1) i.r2" ;不要将r1转换为wchar,保留指针以释放它${If} $2 = 0System::Call "*$1(&w${NSIS_MAX_STRLEN} .r0)" ;从指针中获取wchar${IfThen} $1 <>0 ${|} System::Call "netapi32::NetApiBufferFree(ir1)" ${|} ;释放指针${其他}StrCpy $0 ""${endif}流行 $2流行 $1兑换 $0函数结束

解决方案

<> 运算符用于数字,而不是字符串.不过,这不是您唯一的问题;* 可以(通常)只与 i 一起使用,而不是 t/m/w.t/m/w 类型与 C 样式字符串相互转换,但在您的情况下,您需要实际的内存地址,因为您必须通过它的免费功能.

您需要将 *i0r1 传递给 NetGetDCName,然后如果 $2 为 0,则您可以使用结构体语法 (*$1(&w${NSIS_MAX_STRLEN}.r5)*$1(w.r5)) 最后将 $1 原封不动地传递给自由函数...

I am getting system information via the System plugin by using code similar to the answer to my previous question. The API function is very similar except that it returns (or not) a wide char string.

While using that script on a computer that is member of a domain, I cannot understand why the logiclib test always pass in the ${else} branch of the test. The following capture shows that $1 is not null:

While reading more the NetGetDCName reference I think that it would be preferable to check the function returned value instead of the wide char string pointer. I am a bit confused, why does my ${If} 0 <> $1 always fails? I have checked on a virtual machine not member of a domain that $1 equals 0 in this case. I suppose then that the ${IfThen} test to free the memory is wrong too.

Here is the sample code:

!include "logiclib.nsh"
outfile "hello2.exe"

!define DEBUG `System::Call kernel32::OutputDebugString(ts)`

section

    Call GetDCName
    pop $0

    Messagebox MB_OK "DCName=$0"

sectionEnd

Function GetDCName
    ;Push the domain controler name to the stack (or an empty string if no dc)
    push $0
    push $1
    push $2
    System::Call "netapi32::NetGetDCName(i0, i0, *w 0 r1) i.r2"
    Dumpstate::debug
    ${If} 0 <> $1
        ${debug} "copy $1"
        StrCpy $0 $1
    ${else}
        ${debug} "copy empty string"
        StrCpy $0 ""
    ${endif}
    ${IfThen} $1 <> 0 ${|} System::Call "netapi32::NetApiBufferFree(ir1)" ${|}
    Pop $2
    Pop $1
    Exch $0
FunctionEnd

Edit: thanks to Anders, here is the corrected function:

Function GetDCName
    ;Push the domain controler name to the stack (or an empty string if no dc)
    push $0
    push $1
    push $2
    System::Call "netapi32::NetGetDCName(i0, i0, *i 0 r1) i.r2" ;do not convert r1 to wchar, keep the pointer to free it
    ${If} $2 = 0
        System::Call "*$1(&w${NSIS_MAX_STRLEN} .r0)"        ;get the wchar from the pointer
        ${IfThen} $1 <> 0 ${|} System::Call "netapi32::NetApiBufferFree(ir1)" ${|}  ;free the pointer
    ${else}
        StrCpy $0 ""
    ${endif}
    Pop $2
    Pop $1
    Exch $0
FunctionEnd

解决方案

The <> operator is for numbers, not strings. This is not your only problem though; * can (normally) only be used with i, not t/m/w. The t/m/w types convert to and from C style strings but in your case you need the actual memory address since you have to pass it to the free function.

You need to pass *i0r1 to NetGetDCName, then if $2 is 0 then you can extract the string with the struct syntax (*$1(&w${NSIS_MAX_STRLEN}.r5) or *$1(w.r5)) and finally pass $1 untouched to the free function...

这篇关于测试系统插件返回的字符串时出现意外的 logiclib 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆