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

GetVolumePathNameW

関数
ファイルパスからそのボリュームのマウントパスを取得する。
DLLKERNEL32.dll文字セットUnicode (-W)呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

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

BOOL GetVolumePathNameW(
    LPCWSTR lpszFileName,
    LPWSTR lpszVolumePathName,
    DWORD cchBufferLength
);

パラメーター

名前方向説明
lpszFileNameLPCWSTRin

入力パス文字列へのポインターです。このパスには、絶対パスと相対パスの両方を指定でき、ファイル名・ディレクトリ名(例: "..")も使用できます。

ボリューム修飾子を付けずに相対ディレクトリ名またはファイル名を指定した場合、GetVolumePathName はブートボリュームのドライブ文字を返します。

このパラメーターが空文字列 "" の場合、関数は失敗しますが、最終エラーは ERROR_SUCCESS に設定されます。

lpszVolumePathNameLPWSTRout入力パスに対応するボリュームのマウントポイントを受け取る文字列へのポインターです。
cchBufferLengthDWORDin出力バッファーの長さ(TCHAR 単位)です。

戻り値の型: BOOL

公式ドキュメント

指定したパスがマウントされているボリュームのマウントポイントを取得します。(GetVolumePathNameW)

戻り値

関数が成功した場合、戻り値は 0 以外の値になります。

関数が失敗した場合、戻り値は 0 になります。拡張エラー情報を取得するには、GetLastError を呼び出します。

解説(Remarks)

指定したパスが渡されると、GetVolumePathName はボリュームのマウントポイントへのパスを返します。つまり、指定したパスの末端が存在するボリュームのルートを返します。

たとえば、ボリューム D が C:\Mnt\Ddrive にマウントされ、ボリューム E が C:\Mnt\Ddrive\Mnt\Edrive にマウントされているとします。また、パス E:\Dir\Subdir\MyFile を持つファイルがあるとします。この場合、C:\Mnt\Ddrive\Mnt\Edrive\Dir\Subdir\MyFileGetVolumePathName に渡すと、パス C:\Mnt\Ddrive\Mnt\Edrive\ が返されます。

ボリューム修飾子を付けずに相対ディレクトリまたはファイルを渡した場合、関数はブートボリュームのドライブ文字を返します。有効なボリューム修飾子を付けずに無効なファイル名またはディレクトリ名を指定した場合も、ブートボリュームのドライブ文字が返されます。有効なボリューム指定子が与えられ、そのボリュームが存在するものの、無効なファイル名またはディレクトリ名が指定された場合、関数は成功し、そのボリューム名が返されます。例については、本トピックの「例」のセクションを参照してください。

有効な Win32 名前空間パスを指定する必要があります。NT 名前空間パス(例: \DosDevices\H:\Device\HardDiskVolume6)を指定した場合、関数はその NT 名前空間パスのドライブ文字ではなく、ブートボリュームのドライブ文字を返します。

パス名と名前空間の詳細については、ファイル、パス、名前空間の名前付けを参照してください。

ローカルパスとリモートパスの両方を指定できます。ローカルパスを指定した場合、GetVolumePathName は、ボリュームを表す最も長いプレフィックスをプレフィックスとするフルパスを返します。

ネットワーク共有を指定した場合、GetVolumePathName は、GetDriveTypeDRIVE_REMOTE を返す最も短いパスを返します。これは、そのパスが、存在し現在のユーザーがアクセスできるリモートドライブとして検証されることを意味します。

末尾の円記号が返されない特殊なケースがあります。これは、出力バッファーの長さが 1 文字だけ不足している場合に発生します。たとえば、lpszFileNameC:lpszVolumePathName の長さが 4 文字の場合、返される値は C:\ ですが、lpszVolumePathName の長さが 3 文字の場合、返される値は C: になります。戻り値バッファーのサイズを設定する、より安全ですが低速な方法として、GetFullPathName 関数を呼び出し、バッファーサイズが少なくとも GetFullPathName が返すフルパスと同じサイズになるようにする方法があります。出力バッファーが 1 文字を超えて不足している場合、関数は失敗してエラーを返します。

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

テクノロジ サポート状況
Server Message Block (SMB) 3.0 プロトコル いいえ
SMB 3.0 トランスペアレントフェールオーバー (TFO) いいえ
SMB 3.0 スケールアウトファイル共有 (SO) いいえ
クラスター共有ボリュームファイルシステム (CsvFS) はい
ReFS (Resilient File System) はい

SMB はボリューム管理関数をサポートしていません。

末尾のパス要素

無効な末尾のパス要素は無視されます。リモートパスの場合、次のいずれかの条件が真であれば、(末尾の要素だけでなく)パス全体が無効と見なされます。

ジャンクションポイントとマウントされたフォルダー

指定したパスがジャンクションポイントを通過する場合、GetVolumePathName はそのジャンクションポイントが参照するボリュームを返します。たとえば、W:\AdirC:\Adir を指すジャンクションポイントである場合、W:\Adir\Afile に対して GetVolumePathName を呼び出すと C:\ が返されます。指定したパスが複数のジャンクションポイントを通過する場合、チェーン全体がたどられ、GetVolumePathName はチェーン内の最後のジャンクションポイントが参照するボリュームを返します。

マウントされたフォルダーまたはジャンクションポイントへのリモートパスが指定された場合、そのパスはリモートパスとして解析され、マウントされたフォルダーまたはジャンクションポイントは無視されます。たとえば、C:\Dir_CD:\Dir_D にリンクされており、リモートコンピューターで C:X: にマップされている場合、リモートコンピューター上で X:\Dir_C を指定して GetVolumePathName を呼び出すと X:\ が返されます。

次の一連の例では、U: はリモートコンピューター \\_YourComputer_\C$ にマップされており、Q はローカルドライブです。

指定したパス 関数の戻り値
\\_YourComputer_\C$\Windows \\_YourComputer_\C$\
\\?\UNC\_YourComputer_\C$\Windows \\?\UNC\_YourComputer_\C$\
Q:\Windows Q:\
\\?\Q:\Windows \\?\Q:\
\\.\Q:\Windows \\.\Q:\
\\?\UNC\W:\Windows 指定したリモートパスが無効だったため、エラー 123 で FALSE。W$ 共有が存在しないか、ユーザーアクセスが許可されていません。
C:\COM2(存在する) \\.\COM2\
C:\COM3(存在しない) 存在しない COM デバイスが指定されたため、エラー 123 で FALSE

次の一連の例では、パスに無効な末尾のパス要素が含まれています。

指定したパス 関数の戻り値
G:\invalid(無効なパス) G:\
\\.\I:\aaa\invalid(無効なパス) \\.\I:\
\\_YourComputer_\C$\invalid(無効な末尾のパス要素) \\_YourComputer_\C$\
出典・ライセンス: 上記「公式ドキュメント」の内容は 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>

BOOL GetVolumePathNameW(
    LPCWSTR lpszFileName,
    LPWSTR lpszVolumePathName,
    DWORD cchBufferLength
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
static extern bool GetVolumePathNameW(
    [MarshalAs(UnmanagedType.LPWStr)] string lpszFileName,   // LPCWSTR
    [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpszVolumePathName,   // LPWSTR out
    uint cchBufferLength   // DWORD
);
<DllImport("KERNEL32.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function GetVolumePathNameW(
    <MarshalAs(UnmanagedType.LPWStr)> lpszFileName As String,   ' LPCWSTR
    <MarshalAs(UnmanagedType.LPWStr)> lpszVolumePathName As System.Text.StringBuilder,   ' LPWSTR out
    cchBufferLength As UInteger   ' DWORD
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' lpszFileName : LPCWSTR
' lpszVolumePathName : LPWSTR out
' cchBufferLength : DWORD
Declare PtrSafe Function GetVolumePathNameW Lib "kernel32" ( _
    ByVal lpszFileName As LongPtr, _
    ByVal lpszVolumePathName As LongPtr, _
    ByVal cchBufferLength 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

GetVolumePathNameW = ctypes.windll.kernel32.GetVolumePathNameW
GetVolumePathNameW.restype = wintypes.BOOL
GetVolumePathNameW.argtypes = [
    wintypes.LPCWSTR,  # lpszFileName : LPCWSTR
    wintypes.LPWSTR,  # lpszVolumePathName : LPWSTR out
    wintypes.DWORD,  # cchBufferLength : DWORD
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

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

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procGetVolumePathNameW = kernel32.NewProc("GetVolumePathNameW")
)

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

extern "kernel32" fn GetVolumePathNameW(
    lpszFileName: [*c]const u16, // LPCWSTR
    lpszVolumePathName: [*c]u16, // LPWSTR out
    cchBufferLength: u32 // DWORD
) callconv(std.os.windows.WINAPI) i32;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。
proc GetVolumePathNameW(
    lpszFileName: WideCString,  # LPCWSTR
    lpszVolumePathName: ptr uint16,  # LPWSTR out
    cchBufferLength: uint32  # DWORD
): int32 {.importc: "GetVolumePathNameW", stdcall, dynlib: "KERNEL32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。
pragma(lib, "kernel32");
extern(Windows)
int GetVolumePathNameW(
    const(wchar)* lpszFileName,   // LPCWSTR
    wchar* lpszVolumePathName,   // LPWSTR out
    uint cchBufferLength   // DWORD
);
ccall((:GetVolumePathNameW, "KERNEL32.dll"), stdcall, Int32,
      (Cwstring, Ptr{UInt16}, UInt32),
      lpszFileName, lpszVolumePathName, cchBufferLength)
# lpszFileName : LPCWSTR -> Cwstring
# lpszVolumePathName : LPWSTR out -> Ptr{UInt16}
# cchBufferLength : DWORD -> UInt32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。
local ffi = require("ffi")
ffi.cdef[[
int32_t GetVolumePathNameW(
    const uint16_t* lpszFileName,
    uint16_t* lpszVolumePathName,
    uint32_t cchBufferLength);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.GetVolumePathNameW(lpszFileName, lpszVolumePathName, cchBufferLength)
-- lpszFileName : LPCWSTR
-- lpszVolumePathName : LPWSTR out
-- cchBufferLength : DWORD
-- 構造体/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 GetVolumePathNameW = lib.func('__stdcall', 'GetVolumePathNameW', 'int32_t', ['str16', 'uint16_t *', 'uint32_t']);
// GetVolumePathNameW(lpszFileName, lpszVolumePathName, cchBufferLength)
// lpszFileName : LPCWSTR -> 'str16'
// lpszVolumePathName : LPWSTR out -> 'uint16_t *'
// cchBufferLength : DWORD -> 'uint32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("KERNEL32.dll", {
  GetVolumePathNameW: { parameters: ["buffer", "buffer", "u32"], result: "i32" },
});
// lib.symbols.GetVolumePathNameW(lpszFileName, lpszVolumePathName, cchBufferLength)
// lpszFileName : LPCWSTR -> "buffer"
// lpszVolumePathName : LPWSTR out -> "buffer"
// cchBufferLength : DWORD -> "u32"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t GetVolumePathNameW(
    const uint16_t* lpszFileName,
    uint16_t* lpszVolumePathName,
    uint32_t cchBufferLength);
C, "KERNEL32.dll");
// $ffi->GetVolumePathNameW(lpszFileName, lpszVolumePathName, cchBufferLength);
// lpszFileName : LPCWSTR
// lpszVolumePathName : LPWSTR out
// cchBufferLength : DWORD
// 構造体/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);
    boolean GetVolumePathNameW(
        WString lpszFileName,   // LPCWSTR
        char[] lpszVolumePathName,   // LPWSTR out
        int cchBufferLength   // DWORD
    );
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。
@[Link("kernel32")]
lib LibKERNEL32
  fun GetVolumePathNameW = GetVolumePathNameW(
    lpszFileName : UInt16*,   # LPCWSTR
    lpszVolumePathName : UInt16*,   # LPWSTR out
    cchBufferLength : UInt32   # DWORD
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef GetVolumePathNameWNative = Int32 Function(Pointer<Utf16>, Pointer<Utf16>, Uint32);
typedef GetVolumePathNameWDart = int Function(Pointer<Utf16>, Pointer<Utf16>, int);
final GetVolumePathNameW = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<GetVolumePathNameWNative, GetVolumePathNameWDart>('GetVolumePathNameW');
// lpszFileName : LPCWSTR -> Pointer<Utf16>
// lpszVolumePathName : LPWSTR out -> Pointer<Utf16>
// cchBufferLength : DWORD -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function GetVolumePathNameW(
  lpszFileName: PWideChar;   // LPCWSTR
  lpszVolumePathName: PWideChar;   // LPWSTR out
  cchBufferLength: DWORD   // DWORD
): BOOL; stdcall;
  external 'KERNEL32.dll' name 'GetVolumePathNameW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "GetVolumePathNameW"
  c_GetVolumePathNameW :: CWString -> CWString -> Word32 -> IO CInt
-- lpszFileName : LPCWSTR -> CWString
-- lpszVolumePathName : LPWSTR out -> CWString
-- cchBufferLength : DWORD -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let getvolumepathnamew =
  foreign "GetVolumePathNameW"
    ((ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> returning int32_t)
(* lpszFileName : LPCWSTR -> (ptr uint16_t) *)
(* lpszVolumePathName : LPWSTR out -> (ptr uint16_t) *)
(* cchBufferLength : DWORD -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("GetVolumePathNameW" get-volume-path-name-w :convention :stdcall) :int32
  (lpsz-file-name (:string :encoding :utf-16le))   ; LPCWSTR
  (lpsz-volume-path-name :pointer)   ; LPWSTR out
  (cch-buffer-length :uint32))   ; DWORD
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $GetVolumePathNameW = Win32::API::More->new('KERNEL32',
    'BOOL GetVolumePathNameW(LPCWSTR lpszFileName, LPWSTR lpszVolumePathName, DWORD cchBufferLength)');
# my $ret = $GetVolumePathNameW->Call($lpszFileName, $lpszVolumePathName, $cchBufferLength);
# lpszFileName : LPCWSTR -> LPCWSTR
# lpszVolumePathName : LPWSTR out -> LPWSTR
# cchBufferLength : DWORD -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。

関連項目

文字セット違い