测试系统插件返回的字符串时出现意外的 logiclib 行为 [英] unexpected logiclib behavior when testing string returned by system plugin
问题描述
我使用类似于 我认为最好检查函数返回值而不是宽字符字符串指针.我有点困惑,为什么我的 ${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屋!