シンボリックリンクや、ジャンクションなどのリパースポイントの情報を取得します。 リパースポイントの情報は、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