わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。

リパースポイントの情報を取得する

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




わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。