0

システム プラグインとnetapi32ライブラリを介して Windows から情報を取得しようとしています。

NetWkstaGetInfo()として適切な構造体を割り当ててから呼び出すようにしていWKSTA_INFO_100ます。

NetWkstaGetInfo()プロトタイプは MSDN で次のように述べています。

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 呼び出しによって置き換えられるかどうかを確認します。

しかし、これまで、最初の構造体メンバーの後にほとんど何も得られませんでした。構造体が正しく定義されていないか、構造体の配置に問題があると思います。残念ながら、System プラグインの奇妙なドキュメントに頭がおかしくなり、あまり役に立ちません。

ここに私のテストスクリプトがあります:

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プラグインのパラメータは必須ですか? いくつかの例を見つけましたが、正確な理由は見つかりませんでした。割り当てられた構造体がパラメーターなしで時期尚早に解放されるのではないかと心配しました。確認/確認していただけますか?
4

2 に答える 2

0

ドキュメントとMSDNに従うと、構造体の最初のメンバーはそうiではないはずですが、 (Dumpstateプラグインはアドレスとして返されることを示す傾向があります)*iなしでは正しい戻り値を取得できませんでした*

それが解決策の手がかりでした。MSDNページを読み間違えたのですが、最初は、渡される構造体ではなく、API呼び出しによって変更される(そして後で解放する必要がNetWkstaGetInfo ある)アドレスである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
于 2012-09-10T15:19:01.003 に答える
0

bufptr は出力のみであるため、NetWkstaGetInfo への入力として r0 を渡すことは無意味です。関数は入力データを必要としません。*iNetApiBufferFree と一緒に使用するべきではありません。i単独で十分です ($0 には既にアドレスがあり、システム プラグインがポインターを操作したくない場合は、API に直接渡すだけです)。

!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は、関数の開始前に $0 が NULL になるように bufptr パラメーターを使用しました (このトリックを使用したくない場合は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 によって割り当てられたメモリのブロックです。

于 2012-09-10T19:28:08.520 に答える