Win32 API 日本語リファレンス
ホームStorage.FileSystem › GetFinalPathNameByHandleW

GetFinalPathNameByHandleW

関数
ファイルハンドルから最終的なパス名を取得する。
DLLKERNEL32.dll文字セットUnicode (-W)呼出規約winapiSetLastErrorあり対応OSWindows Vista 以降

シグネチャ

// KERNEL32.dll  (Unicode / -W)
#include <windows.h>

DWORD GetFinalPathNameByHandleW(
    HANDLE hFile,
    LPWSTR lpszFilePath,
    DWORD cchFilePath,
    GETFINALPATHNAMEBYHANDLE_FLAGS dwFlags
);

パラメーター

名前方向説明
hFileHANDLEinファイルまたはディレクトリへのハンドル。
lpszFilePathLPWSTRouthFile のパスを受け取るバッファへのポインター。
cchFilePathDWORDinlpszFilePath のサイズ(TCHAR 単位)。この値には NULL 終端文字を含める必要があります。
dwFlagsGETFINALPATHNAMEBYHANDLE_FLAGSin

返す結果の種類。このパラメーターには次のいずれかの値を指定できます。

意味
FILE_NAME_NORMALIZED
0x0
正規化されたドライブ名を返します。これが既定値です。
FILE_NAME_OPENED
0x8
開かれたファイル名(正規化されていない)を返します。

このパラメーターには、さらに次のいずれかの値を含めることができます。

意味
VOLUME_NAME_DOS
0x0
ドライブ文字を含むパスを返します。これが既定値です。
VOLUME_NAME_GUID
0x1
ドライブ名の代わりにボリューム GUID パスを含むパスを返します。
VOLUME_NAME_NONE
0x4
ドライブ情報を含まないパスを返します。
VOLUME_NAME_NT
0x2
NT デバイスオブジェクトのパスを返します。

戻り値の型: DWORD

公式ドキュメント

指定したファイルの最終パスを取得します。(Unicode)

戻り値

関数が成功した場合、戻り値は lpszFilePath が受け取った文字列の長さ(TCHAR 単位)です。この値には終端の NULL 文字のサイズは含まれません。

Windows Server 2008 および Windows Vista: この関数の ANSI 版である GetFinalPathNameByHandleA では、戻り値に終端の NULL 文字のサイズが含まれます。

lpszFilePath が文字列と終端の NULL 文字を格納するには小さすぎるために関数が失敗した場合、戻り値は必要なバッファサイズ(TCHAR 単位)です。この値には終端の NULL 文字のサイズが含まれます。

それ以外の理由で関数が失敗した場合、戻り値はゼロです。拡張エラー情報を取得するには、 GetLastError を呼び出します。

戻りコード 説明
ERROR_PATH_NOT_FOUND
ドライブ文字を検索しているのにそれが存在しない場合に返されることがあります。たとえば、現在マウントされていないドライブでハンドルが開かれた場合や、ボリュームを作成してドライブ文字を割り当てなかった場合などです。ボリュームにドライブ文字がない場合は、ボリューム GUID パスを使用して識別できます。

この戻り値は、ネットワーク共有でボリューム GUID パスを検索している場合にも返されることがあります。ネットワーク共有に対してはボリューム GUID パスは作成されません。

ERROR_NOT_ENOUGH_MEMORY
操作を完了するためのメモリが不足しています。
ERROR_INVALID_PARAMETER
dwFlags に無効なフラグが指定されました。

解説(Remarks)

Server Message Block (SMB) プロトコルは、正規化されたパスへのクエリをサポートしていません。そのため、SMB を使用して開いたファイルのハンドルを FILE_NAME_NORMALIZED フラグとともにこの関数に渡して呼び出すと、関数はパスを各構成要素に分割し、それぞれの構成要素について順番に正規化された名前のクエリを試みます。ユーザーがこれらの構成要素のいずれかへのアクセス許可を持っていない場合、関数呼び出しは ERROR_ACCESS_DENIED で失敗します。

最終パスとは、パスが完全に解決されたときに返されるパスです。たとえば、"D:\yourdir" を指す "C:\tmp\mydir" という名前のシンボリックリンクの場合、最終パスは "D:\yourdir" となります。

VOLUME_NAME_DOS を使用する場合、この関数が返す文字列は "\\?\" 構文を使用します。詳細については、CreateFile を参照してください。

VOLUME_NAME_GUID を使用する場合、返されるパスは "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\" のような形式のボリューム GUID パスで始まります。

VOLUME_NAME_NT を使用する場合、返されるパスは NT デバイスオブジェクトのパスであり、"\Device\HarddiskVolume1\" のようなデバイス名で始まります。この種類のパスは相対パスに似ているため、Windows プログラムから直接使用することはできません。

一部のサードパーティ製ドライバーは、Mount Manager を使用せずにドライブ文字またはマウントポイントを作成することがあります。ドライブの作成に Mount Manager が使用されなかった場合、VOLUME_NAME_DOS または VOLUME_NAME_GUID は成功せず、VOLUME_NAME_NT のみが利用可能になります。ボリュームデバイスパスのドライブ文字を特定するには、一致するデバイス名が見つかるまで、すべてのドライブ文字に対して QueryDosDevice 関数を使用します。

Windows 8 および Windows Server 2012 では、この関数は次のテクノロジによってサポートされています。

テクノロジ サポート
Server Message Block (SMB) 3.0 プロトコル はい
SMB 3.0 透過的フェールオーバー (TFO) はい
スケールアウトファイル共有 (SO) を使用した SMB 3.0 はい
クラスター共有ボリュームファイルシステム (CsvFS) はい
回復性ファイルシステム (ReFS) はい

次の例は、 GetFinalPathNameByHandle 関数の使用方法を示しています。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#define BUFSIZE MAX_PATH

void __cdecl _tmain(int argc, TCHAR *argv[])
{
    TCHAR Path[BUFSIZE];
    HANDLE hFile;
    DWORD dwRet;

    printf("\n");
    if( argc != 2 )
    {
        printf("ERROR:\tIncorrect number of arguments\n\n");
        printf("%s <file_name>\n", argv[0]);
        return;
    }

    hFile = CreateFile(argv[1],               // file to open
                       GENERIC_READ,          // open for reading
                       FILE_SHARE_READ,       // share for reading
                       NULL,                  // default security
                       OPEN_EXISTING,         // existing file only
                       FILE_ATTRIBUTE_NORMAL, // normal file
                       NULL);                 // no attr. template

    if( hFile == INVALID_HANDLE_VALUE)
    {
        printf("Could not open file (error %d\n)", GetLastError());
        return;
    }

    dwRet = GetFinalPathNameByHandle( hFile, Path, BUFSIZE, VOLUME_NAME_NT );
    if(dwRet < BUFSIZE)
    {
        _tprintf(TEXT("\nThe final path is: %s\n"), Path);
    }
    else printf("\nThe required buffer size is %d.\n", dwRet);

    CloseHandle(hFile);
}
メモ

fileapi.h ヘッダーは、UNICODE プリプロセッサ定数の定義に基づいて、この関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして GetFinalPathNameByHandle を定義します。エンコーディング中立のエイリアスの使用を、エンコーディング中立でないコードと混在させると、コンパイルエラーまたは実行時エラーを引き起こす不一致が生じる可能性があります。詳細については、関数プロトタイプの規則を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// KERNEL32.dll  (Unicode / -W)
#include <windows.h>

DWORD GetFinalPathNameByHandleW(
    HANDLE hFile,
    LPWSTR lpszFilePath,
    DWORD cchFilePath,
    GETFINALPATHNAMEBYHANDLE_FLAGS dwFlags
);
[DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
static extern uint GetFinalPathNameByHandleW(
    IntPtr hFile,   // HANDLE
    [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpszFilePath,   // LPWSTR out
    uint cchFilePath,   // DWORD
    uint dwFlags   // GETFINALPATHNAMEBYHANDLE_FLAGS
);
<DllImport("KERNEL32.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function GetFinalPathNameByHandleW(
    hFile As IntPtr,   ' HANDLE
    <MarshalAs(UnmanagedType.LPWStr)> lpszFilePath As System.Text.StringBuilder,   ' LPWSTR out
    cchFilePath As UInteger,   ' DWORD
    dwFlags As UInteger   ' GETFINALPATHNAMEBYHANDLE_FLAGS
) As UInteger
End Function
' hFile : HANDLE
' lpszFilePath : LPWSTR out
' cchFilePath : DWORD
' dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS
Declare PtrSafe Function GetFinalPathNameByHandleW Lib "kernel32" ( _
    ByVal hFile As LongPtr, _
    ByVal lpszFilePath As LongPtr, _
    ByVal cchFilePath As Long, _
    ByVal dwFlags As Long) As Long
' Unicode(W): 文字列は ByVal As LongPtr とし StrPtr(unicodeStr) を渡す
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

GetFinalPathNameByHandleW = ctypes.windll.kernel32.GetFinalPathNameByHandleW
GetFinalPathNameByHandleW.restype = wintypes.DWORD
GetFinalPathNameByHandleW.argtypes = [
    wintypes.HANDLE,  # hFile : HANDLE
    wintypes.LPWSTR,  # lpszFilePath : LPWSTR out
    wintypes.DWORD,  # cchFilePath : DWORD
    wintypes.DWORD,  # dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('KERNEL32.dll')
GetFinalPathNameByHandleW = Fiddle::Function.new(
  lib['GetFinalPathNameByHandleW'],
  [
    Fiddle::TYPE_VOIDP,  # hFile : HANDLE
    Fiddle::TYPE_VOIDP,  # lpszFilePath : LPWSTR out
    -Fiddle::TYPE_INT,  # cchFilePath : DWORD
    -Fiddle::TYPE_INT,  # dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS
  ],
  -Fiddle::TYPE_INT)
# Wide strings: pass str.encode("UTF-16LE") + "\x00\x00"
#[link(name = "kernel32")]
extern "system" {
    fn GetFinalPathNameByHandleW(
        hFile: *mut core::ffi::c_void,  // HANDLE
        lpszFilePath: *mut u16,  // LPWSTR out
        cchFilePath: u32,  // DWORD
        dwFlags: u32  // GETFINALPATHNAMEBYHANDLE_FLAGS
    ) -> u32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern uint GetFinalPathNameByHandleW(IntPtr hFile, [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_GetFinalPathNameByHandleW' -Namespace Win32 -PassThru
# $api::GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
#uselib "KERNEL32.dll"
#func global GetFinalPathNameByHandleW "GetFinalPathNameByHandleW" wptr, wptr, wptr, wptr
; GetFinalPathNameByHandleW hFile, varptr(lpszFilePath), cchFilePath, dwFlags   ; 戻り値は stat
; hFile : HANDLE -> "wptr"
; lpszFilePath : LPWSTR out -> "wptr"
; cchFilePath : DWORD -> "wptr"
; dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> "wptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "KERNEL32.dll"
#cfunc global GetFinalPathNameByHandleW "GetFinalPathNameByHandleW" sptr, var, int, int
; res = GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
; hFile : HANDLE -> "sptr"
; lpszFilePath : LPWSTR out -> "var"
; cchFilePath : DWORD -> "int"
; dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> "int"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; DWORD GetFinalPathNameByHandleW(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, GETFINALPATHNAMEBYHANDLE_FLAGS dwFlags)
#uselib "KERNEL32.dll"
#cfunc global GetFinalPathNameByHandleW "GetFinalPathNameByHandleW" intptr, var, int, int
; res = GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
; hFile : HANDLE -> "intptr"
; lpszFilePath : LPWSTR out -> "var"
; cchFilePath : DWORD -> "int"
; dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> "int"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procGetFinalPathNameByHandleW = kernel32.NewProc("GetFinalPathNameByHandleW")
)

// hFile (HANDLE), lpszFilePath (LPWSTR out), cchFilePath (DWORD), dwFlags (GETFINALPATHNAMEBYHANDLE_FLAGS)
r1, _, err := procGetFinalPathNameByHandleW.Call(
	uintptr(hFile),
	uintptr(lpszFilePath),
	uintptr(cchFilePath),
	uintptr(dwFlags),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // DWORD
function GetFinalPathNameByHandleW(
  hFile: THandle;   // HANDLE
  lpszFilePath: PWideChar;   // LPWSTR out
  cchFilePath: DWORD;   // DWORD
  dwFlags: DWORD   // GETFINALPATHNAMEBYHANDLE_FLAGS
): DWORD; stdcall;
  external 'KERNEL32.dll' name 'GetFinalPathNameByHandleW';
result := DllCall("KERNEL32\GetFinalPathNameByHandleW"
    , "Ptr", hFile   ; HANDLE
    , "Ptr", lpszFilePath   ; LPWSTR out
    , "UInt", cchFilePath   ; DWORD
    , "UInt", dwFlags   ; GETFINALPATHNAMEBYHANDLE_FLAGS
    , "UInt")   ; return: DWORD
●GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags) = DLL("KERNEL32.dll", "dword GetFinalPathNameByHandleW(void*, char*, dword, dword)")
# 呼び出し: GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
# hFile : HANDLE -> "void*"
# lpszFilePath : LPWSTR out -> "char*"
# cchFilePath : DWORD -> "dword"
# dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> "dword"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
# ※-W(Unicode)関数。なでしこ1はANSIのため -A 版の利用を推奨。
const std = @import("std");

extern "kernel32" fn GetFinalPathNameByHandleW(
    hFile: ?*anyopaque, // HANDLE
    lpszFilePath: [*c]u16, // LPWSTR out
    cchFilePath: u32, // DWORD
    dwFlags: u32 // GETFINALPATHNAMEBYHANDLE_FLAGS
) callconv(std.os.windows.WINAPI) u32;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。
proc GetFinalPathNameByHandleW(
    hFile: pointer,  # HANDLE
    lpszFilePath: ptr uint16,  # LPWSTR out
    cchFilePath: uint32,  # DWORD
    dwFlags: uint32  # GETFINALPATHNAMEBYHANDLE_FLAGS
): uint32 {.importc: "GetFinalPathNameByHandleW", stdcall, dynlib: "KERNEL32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。
pragma(lib, "kernel32");
extern(Windows)
uint GetFinalPathNameByHandleW(
    void* hFile,   // HANDLE
    wchar* lpszFilePath,   // LPWSTR out
    uint cchFilePath,   // DWORD
    uint dwFlags   // GETFINALPATHNAMEBYHANDLE_FLAGS
);
ccall((:GetFinalPathNameByHandleW, "KERNEL32.dll"), stdcall, UInt32,
      (Ptr{Cvoid}, Ptr{UInt16}, UInt32, UInt32),
      hFile, lpszFilePath, cchFilePath, dwFlags)
# hFile : HANDLE -> Ptr{Cvoid}
# lpszFilePath : LPWSTR out -> Ptr{UInt16}
# cchFilePath : DWORD -> UInt32
# dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> UInt32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。
local ffi = require("ffi")
ffi.cdef[[
uint32_t GetFinalPathNameByHandleW(
    void* hFile,
    uint16_t* lpszFilePath,
    uint32_t cchFilePath,
    uint32_t dwFlags);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
-- hFile : HANDLE
-- lpszFilePath : LPWSTR out
-- cchFilePath : DWORD
-- dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
-- Unicode(-W): uint16_t* には UTF-16LE のバッファ(ffi.new("uint16_t[?]", ...))を渡す。
const koffi = require('koffi');
const lib = koffi.load('KERNEL32.dll');
const GetFinalPathNameByHandleW = lib.func('__stdcall', 'GetFinalPathNameByHandleW', 'uint32_t', ['void *', 'uint16_t *', 'uint32_t', 'uint32_t']);
// GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
// hFile : HANDLE -> 'void *'
// lpszFilePath : LPWSTR out -> 'uint16_t *'
// cchFilePath : DWORD -> 'uint32_t'
// dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> 'uint32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("KERNEL32.dll", {
  GetFinalPathNameByHandleW: { parameters: ["pointer", "buffer", "u32", "u32"], result: "u32" },
});
// lib.symbols.GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags)
// hFile : HANDLE -> "pointer"
// lpszFilePath : LPWSTR out -> "buffer"
// cchFilePath : DWORD -> "u32"
// dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> "u32"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
uint32_t GetFinalPathNameByHandleW(
    void* hFile,
    uint16_t* lpszFilePath,
    uint32_t cchFilePath,
    uint32_t dwFlags);
C, "KERNEL32.dll");
// $ffi->GetFinalPathNameByHandleW(hFile, lpszFilePath, cchFilePath, dwFlags);
// hFile : HANDLE
// lpszFilePath : LPWSTR out
// cchFilePath : DWORD
// dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
    int GetFinalPathNameByHandleW(
        Pointer hFile,   // HANDLE
        char[] lpszFilePath,   // LPWSTR out
        int cchFilePath,   // DWORD
        int dwFlags   // GETFINALPATHNAMEBYHANDLE_FLAGS
    );
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。
@[Link("kernel32")]
lib LibKERNEL32
  fun GetFinalPathNameByHandleW = GetFinalPathNameByHandleW(
    hFile : Void*,   # HANDLE
    lpszFilePath : UInt16*,   # LPWSTR out
    cchFilePath : UInt32,   # DWORD
    dwFlags : UInt32   # GETFINALPATHNAMEBYHANDLE_FLAGS
  ) : UInt32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef GetFinalPathNameByHandleWNative = Uint32 Function(Pointer<Void>, Pointer<Utf16>, Uint32, Uint32);
typedef GetFinalPathNameByHandleWDart = int Function(Pointer<Void>, Pointer<Utf16>, int, int);
final GetFinalPathNameByHandleW = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<GetFinalPathNameByHandleWNative, GetFinalPathNameByHandleWDart>('GetFinalPathNameByHandleW');
// hFile : HANDLE -> Pointer<Void>
// lpszFilePath : LPWSTR out -> Pointer<Utf16>
// cchFilePath : DWORD -> Uint32
// dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function GetFinalPathNameByHandleW(
  hFile: THandle;   // HANDLE
  lpszFilePath: PWideChar;   // LPWSTR out
  cchFilePath: DWORD;   // DWORD
  dwFlags: DWORD   // GETFINALPATHNAMEBYHANDLE_FLAGS
): DWORD; stdcall;
  external 'KERNEL32.dll' name 'GetFinalPathNameByHandleW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "GetFinalPathNameByHandleW"
  c_GetFinalPathNameByHandleW :: Ptr () -> CWString -> Word32 -> Word32 -> IO Word32
-- hFile : HANDLE -> Ptr ()
-- lpszFilePath : LPWSTR out -> CWString
-- cchFilePath : DWORD -> Word32
-- dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let getfinalpathnamebyhandlew =
  foreign "GetFinalPathNameByHandleW"
    ((ptr void) @-> (ptr uint16_t) @-> uint32_t @-> uint32_t @-> returning uint32_t)
(* hFile : HANDLE -> (ptr void) *)
(* lpszFilePath : LPWSTR out -> (ptr uint16_t) *)
(* cchFilePath : DWORD -> uint32_t *)
(* dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("GetFinalPathNameByHandleW" get-final-path-name-by-handle-w :convention :stdcall) :uint32
  (h-file :pointer)   ; HANDLE
  (lpsz-file-path :pointer)   ; LPWSTR out
  (cch-file-path :uint32)   ; DWORD
  (dw-flags :uint32))   ; GETFINALPATHNAMEBYHANDLE_FLAGS
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $GetFinalPathNameByHandleW = Win32::API::More->new('KERNEL32',
    'DWORD GetFinalPathNameByHandleW(HANDLE hFile, LPWSTR lpszFilePath, DWORD cchFilePath, DWORD dwFlags)');
# my $ret = $GetFinalPathNameByHandleW->Call($hFile, $lpszFilePath, $cchFilePath, $dwFlags);
# hFile : HANDLE -> HANDLE
# lpszFilePath : LPWSTR out -> LPWSTR
# cchFilePath : DWORD -> DWORD
# dwFlags : GETFINALPATHNAMEBYHANDLE_FLAGS -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。

関連項目

文字セット違い
使用する型