シンボリックリンクや、ジャンクションなどのリパースポイントの情報を取得します。 リパースポイントの情報は、DeviceIoControlにFSCTL_GET_REPARSE_POINTを渡すことで取得できます。
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <windows.h>
#include <Shlobj.h>
/*
REPARSE_DATA_BUFFER
*/
#ifndef REPARSE_DATA_BUFFER
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#endif
/*
リバースポイントの情報を取得する
*/
HRESULT GetReparsePointInfo
(
LPCWSTR pFilePath // ファイルパス
, ULONG& qReparseTag // リバースタグ( 0ならリバースポイントではない、それ以外はリバースポイントタグが返る )
, std::wstring& strLinkPath // リンクパス
, std::wstring& strDispName // 表示名称
)
{
BOOL bRet = 0;
HRESULT hResult = S_OK;
HANDLE hFile = INVALID_HANDLE_VALUE;
// 情報取得用バッファサイズ
DWORD dwBufferSize = 1024 * 64;
// 情報取得用メモリのポインタ
BYTE* bpInfoBuffer = NULL;
// リバースポイントかどうか
BOOL bReparsePoint = FALSE;
// リバースポイントではない
qReparseTag = 0;
/*
先にファイル属性を確認する
*/
DWORD dwFileAttr = ::GetFileAttributes( pFilePath );
if ( -1 == dwFileAttr ) {
// エラー
std::wcout << L"GetFileAttributes fail" << std::endl;
hResult = ::HRESULT_FROM_WIN32( ::GetLastError() );
goto err;
}
if ( 0 == ( FILE_ATTRIBUTE_REPARSE_POINT & dwFileAttr ) ) {
// リバースポイントでは無い
return( S_OK );
}
/*
情報取得用メモリの確保
*/
bpInfoBuffer = (BYTE*)malloc( dwBufferSize );
if ( NULL == bpInfoBuffer ) {
// メモリ不足
hResult = E_OUTOFMEMORY;
goto err;
}
/*
ファイルのオープン
*/
hFile = CreateFile(
pFilePath
, GENERIC_READ
, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT
, NULL
);
if ( INVALID_HANDLE_VALUE == hFile ) {
// エラー
std::wcout << L"CreateFile fail" << std::endl;
hResult = ::HRESULT_FROM_WIN32( ::GetLastError() );
goto err;
}
{
DWORD dwReadSize = 0;
// DeviceIoControl呼び出し
bRet = DeviceIoControl(
hFile
, FSCTL_GET_REPARSE_POINT
, NULL
, 0
, bpInfoBuffer
, dwBufferSize
, &dwReadSize
, NULL
);
REPARSE_DATA_BUFFER* tpReparseDataBuffer = (_REPARSE_DATA_BUFFER*)bpInfoBuffer;
// マイクロソフト定義のタグか?
DWORD dwIsMSTag = IsReparseTagMicrosoft( tpReparseDataBuffer->ReparseTag );
if ( dwIsMSTag != 0 ) {
/*
tagで分岐
*/
qReparseTag = tpReparseDataBuffer->ReparseTag;
switch( qReparseTag ) {
case IO_REPARSE_TAG_MOUNT_POINT:
// ジャンクション
{
// ジャンクションでした。
WCHAR* wpPathBuffer = (WCHAR*)tpReparseDataBuffer->MountPointReparseBuffer.PathBuffer;
// リンク先の取得
strLinkPath = std::wstring(
&wpPathBuffer[ tpReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset / 2 ]
, &wpPathBuffer[ ( tpReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset + tpReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength ) / 2 ]
);
// 表示名称の取得
strDispName = std::wstring(
&wpPathBuffer[ tpReparseDataBuffer->MountPointReparseBuffer.PrintNameOffset / 2 ]
, &wpPathBuffer[ ( tpReparseDataBuffer->MountPointReparseBuffer.PrintNameOffset + tpReparseDataBuffer->MountPointReparseBuffer.PrintNameLength ) / 2 ]
);
// ジャンクションでした
qReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
}
break;
case IO_REPARSE_TAG_SYMLINK:
// シンボリックリンク
{
// シンボリックリンクでした。
WCHAR* wpPathBuffer = (WCHAR*)tpReparseDataBuffer->SymbolicLinkReparseBuffer.PathBuffer;
// リンク先の取得
strLinkPath = std::wstring(
&wpPathBuffer[ tpReparseDataBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset / 2 ]
, &wpPathBuffer[ ( tpReparseDataBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset + tpReparseDataBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength ) / 2 ]
);
// 表示名称の取得
strDispName = std::wstring(
&wpPathBuffer[ tpReparseDataBuffer->SymbolicLinkReparseBuffer.PrintNameOffset / 2 ]
, &wpPathBuffer[ ( tpReparseDataBuffer->SymbolicLinkReparseBuffer.PrintNameOffset + tpReparseDataBuffer->SymbolicLinkReparseBuffer.PrintNameLength ) / 2 ]
);
// ジャンクションでした
qReparseTag = IO_REPARSE_TAG_SYMLINK;
}
break;
default:
// 知らないタグ(リバースポイントでは無いことにする)
qReparseTag = 0;
break;
}
}
}
err:
// メモリの解放
if ( NULL != bpInfoBuffer ) {
::free( bpInfoBuffer );
}
// 読み込みファイルハンドルのクローズ
if ( INVALID_HANDLE_VALUE != hFile ) {
::CloseHandle( hFile );
}
// 処理結果を返す
return( hResult );
}
/*
リパースポイントの情報を取得する
*/
int _tmain
(
int argc
, _TCHAR* argv[]
)
{
// std::wcoutのロケールを設定
std::wcout.imbue( std::locale( "", std::locale::ctype ) );
ULONG qReparseTag = 0;
std::wstring strLinkPath;
std::wstring strDispName;
// リパースポイントの情報を取得する
HRESULT hResult = GetReparsePointInfo(
L"c:¥¥test¥¥test3.txt" // ファイルパス
, qReparseTag // リバースタグ( 0ならリバースポイントではない、それ以外はリバースポイントタグが返る )
, strLinkPath // リンクパス
, strDispName // 表示名称
);
if ( S_OK == hResult ) {
if ( 0 != qReparseTag ) {
// リパースポイントでした。
std::wcout << L"リパースポイントでした。" << std::endl;
std::wcout << L"リンク先 = " << strLinkPath.c_str() << std::endl;
std::wcout << L"表示名称 = " << strDispName.c_str() << std::endl;
}
else {
// リパースポイントではなかった
std::wcout << L"リパースポイントではなかった。" << std::endl;
}
}
// 正常終了
return( 0 );
}
取得できました。
リンク先 = c:\test\test1.txt
表示名称 = c:\test\test1.txt