小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


ファイルハンドルからファイル名などの情報を取得したい

はじめに

VC++でファイルハンドルからファイル名などのファイル情報を取り出したい。

たとえば、CloseHandleのラッパー関数があって、すべての呼び出し元はこのラッパー関数を使っていたとします。ラッパー関数内でファイルハンドルからファイル情報を取得できれば、どのファイルのファイルハンドルを閉じたかログに出力したりできるようになると考えました。

BOOL CloseHandleWrapper(HANDLE h)
{
	// なんらかの処理

	// close Handle
	BOOL ret = CloseHandle(h);
	return ret;
}
ファイルハンドルからファイル情報を取得する

GetFileInformationByHandleというAPIを使うと、ファイルハンドルからファイル情報を取得できそうだったのですが、残念ながらファイル名は取得できません。

そのかわりに、nFileIndexHighとnFileIndexLowの2つの値が取得できます。

nFileIndexHigh
The high-order part of a unique identifier that is associated with a file. For more information, see nFileIndexLow.
nFileIndexLow
The low-order part of a unique identifier that is associated with a file.

MSDNにはunique identifierの一部とあり、同じファイルであればこの2つの値も一致するはずです。逆に異なるファイルであれば、nFileIndexHighとnFileIndexLowも異なります。

サンプルプログラム

以下のようなサンプルプログラムを作って、GetFileInformationByHandleを使ってみました。

#include "afx.h"
#include <windows.h>

BOOL CloseHandleWrapper(HANDLE);

BOOL CloseHandleWrapper(HANDLE h)
{
  BY_HANDLE_FILE_INFORMATION fi1;

  GetFileInformationByHandle(h, &fi1);
  printf("fi1.nFileIndexHigh::%ld fi1.nFileIndexLow::%ld\n", fi1.nFileIndexHigh, fi1.nFileIndexLow);
  // close Handle
  BOOL ret = CloseHandle(h);

  GetFileInformationByHandle(h, &fi1);
  printf("fi1.nFileIndexHigh::%ld fi1.nFileIndexLow::%ld\n", fi1.nFileIndexHigh, fi1.nFileIndexLow);
  return ret;
}

int _tmain(int argc, _TCHAR *argv[])
{

  // 1.open file
  HANDLE handle1 = CreateFile("c:\\test1.txt" ,
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ ,
                NULL ,
                OPEN_ALWAYS ,
                FILE_ATTRIBUTE_NORMAL ,
                NULL);
  if (handle1 == INVALID_HANDLE_VALUE)
  {
    return 1;
  }

  // 2.seek file
  BOOL ret = SetFilePointer(handle1, NULL, NULL, FILE_END);
  if (ret == INVALID_SET_FILE_POINTER)
  {
    CloseHandleWrapper(handle1);
    return 1;
  }

  // 3. write file
  DWORD dw = 0;
  ret = WriteFile(handle1, "Hellow World\n", sizeof("Hellow World"), &dw, NULL);
  if (ret == FALSE)
  {
    CloseHandleWrapper(handle1);
    return 1;
  }

  // 4. close Handle
  ret = CloseHandleWrapper(handle1);
  if (ret == FALSE)
  {
    return 1;
  }
  handle1 = NULL;

  // 1.open file
  HANDLE handle2 = CreateFile("c:\\test2.txt" ,
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ ,
                NULL ,
                OPEN_ALWAYS ,
                FILE_ATTRIBUTE_NORMAL ,
                NULL);
  if (handle2 == INVALID_HANDLE_VALUE)
  {
    return 1;
  }

  // 2.seek file
  ret = SetFilePointer(handle2, NULL, NULL, FILE_END);
  if (ret == INVALID_SET_FILE_POINTER)
  {
    CloseHandleWrapper(handle2);
    return 1;
  }

  // 3. write file
  dw = 0;
  ret = WriteFile(handle2, "Hellow World\n", sizeof("Hellow World"), &dw, NULL);
  if (ret == FALSE)
  {
    CloseHandleWrapper(handle2);
    return 1;
  }

  // 4. close Handle
  ret = CloseHandleWrapper(handle2);
  if (ret == FALSE)
  {
    return 1;
  }
  handle2 = NULL;

}
実行結果

サンプルプログラムを実行した結果、確かに2つのファイルでは、nFileIndexHighとnFileIndexLowは異なります。
test1.txtは、fi1.nFileIndexHigh::3473408 fi1.nFileIndexLow::73864。test2.txtは、fi1.nFileIndexHigh::9240576 fi1.nFileIndexLow::75317という結果でした。

fi1.nFileIndexHigh::3473408 fi1.nFileIndexLow::73864
fi1.nFileIndexHigh::3473408 fi1.nFileIndexLow::73864
fi1.nFileIndexHigh::9240576 fi1.nFileIndexLow::75317
fi1.nFileIndexHigh::9240576 fi1.nFileIndexLow::75317

関連記事