4

Windows用のJavaアプリでファイルへのハードリンクを列挙する必要があります。でRuntimeを使用することを検討しましfsutil hardlink listたが、管理者権限が必要です。それが私をWINAPIに導きました(うーん)。Kernel32.dll関数のFindFirstFileNameWFindNextFileNameWがこれを行う必要がありますが、JNAAPIを介して呼び出すのに問題があります。FindFirstFileNameWの仕様は次のとおりです。

HANDLE WINAPI FindFirstFileNameW(
 _In_     LPCWSTR lpFileName,
 _In_     DWORD dwFlags,
 _Inout_  LPDWORD StringLength,
 _Inout_  PWCHAR LinkName
);

私のJNAマッピング:

public interface Kernel32 extends StdCallLibrary { 
    Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32",Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
    HANDLE FindFirstFileNameW(WString wString, int dwFlags, IntByReference StringLength, ______ LinkName);

    boolean FindNextFileNameW(HANDLE hFindStream, IntByReference StringLength, ______ LinkName);
    boolean FindClose(HANDLE hFindFile);
    int GetLastError();
}

関数呼び出しの関連部分:

public String[] getHardLInks(Path path)
{
  Kernel32 lib = Kernel32.INSTANCE;
  IntByReference stringLength = new IntByReference();
  ______ linkName = ______;
  HANDLE hFile = lib.FindFirstFileNameW(new WString(path.toString()), 0, stringLength, linkName);
  String hardlink = //Convert linkName to String
  //Add to array
  // Loop through FindNextFileName
  //Close handle
}

LinkName空白は、「最初に見つかったリンク名を格納するためのバッファへのポインタ」を多くのことにマッピングしようlpFileNameとして失敗した場所です。これには、文字列、char []、byte []、Buffer、Pointer、およびMemoryが含まれますが、呼び出しから何も返されません。テストでStringLengthから取得した戻り値から、残りは正しいと思います。ただし、GetLastError常にERROR_MORE_DATA(234)を返します。これは、ドキュメントによると、キロバイトのメモリを渡した場合でも、バッファが小さすぎることを意味します。

どのデータ型を使用する必要があり、それを文字列に戻すにはどうすればよいですか?

4

1 に答える 1

2

PWCHAR=> char[]、ただし、NIOバッファまたはメモリも機能します(バッファとメモリはバイト単位でカウントされますが、APIは文字単位のカウントを想定していることに注意してください)。

また、を配列のサイズに初期化する必要がありIntByReferenceます。そうしないと、バッファのサイズがゼロであることがAPIに通知され、バッファが正確にゼロの文字で素直にいっぱいになります。

この種のほとんどのMSAPI関数と同様に、おそらくバッファーを渡すnullと、必要なバッファーサイズが長さの参照に書き込まれます。

編集

W32API_UNICODE_OPTIONSもう1つ、ライブラリマッピングの初期化に(正しく)使用してStringいるため、ワイド文字列に自動的にマッピングされ(したがって、を使用する必要はありませんWString)、-A/W関数のサフィックスが自動的に処理されるため、-Wメソッド名からサフィックスを削除できます。

于 2013-03-10T01:46:35.490 に答える