C/C++でフォルダ(ディレクトリ)のサイズを取得する

VC++でフォルダ(ディレクトリ)のサイズを取得する例って、検索してもひっかからないんですよね。需要ないのかな。
エラーチェックは中途半端なので、安心して使えませんけど。
"C:\System Volume Information"など、特別なアクセス権が必要なフォルダが含まれていると失敗します。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

typedef unsigned __int64 __uint64;

// DWORD2つからQWORDを作る
inline __uint64 MakeQWord( DWORD hi, DWORD low)
{
	return ((__uint64)hi << 32) | low;
}

// WIN32_FIND_DATAの情報から、ファイルなのかディレクトリなのかを識別する
// GetDirSize関数で使うだけ
bool IsDirectory( WIN32_FIND_DATA *FindData)
{
	return FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
}

// フォルダのサイズを再帰的に調べる。
// アクセス権の関係などで、1つでも失敗したら中止して戻ってくる。
// 戻り値 成功 0 / 失敗 0以外
int GetDirSize( LPCTSTR path, __uint64 *lpSize)
{
	int res = 1;
	*lpSize = 0;
	TCHAR DirSpec[MAX_PATH+1];
//	_stprintf_p( DirSpec, MAX_PATH+1, _T("%s\\*"), path);
	_stprintf( DirSpec, _T("%s\\*"), path);	// BCC用

	WIN32_FIND_DATA FindData;
	HANDLE hFind = FindFirstFile( DirSpec, &FindData);
	if(hFind == INVALID_HANDLE_VALUE)
		goto Error;
	do {
		__uint64 size = 0;
		if(IsDirectory( &FindData)) {
			// ディレクトリ。「.」「..」は無視して、再帰。
			if(!_tcscmp( _T("."), FindData.cFileName) || !_tcscmp( _T(".."), FindData.cFileName))
				continue;
			TCHAR buf[MAX_PATH+1];
//			_stprintf_p( buf, MAX_PATH+1, _T("%s%s\\"), path, FindData.cFileName);
			_stprintf( buf, _T("%s%s\\"), path, FindData.cFileName);	// BCC用
			if(GetDirSize( buf, &size))
				goto Error;
			*lpSize += size;
		}
		else {
			// ファイル
			*lpSize += MakeQWord( FindData.nFileSizeHigh, FindData.nFileSizeLow);
		}

		// デバッグ用
		_tprintf( _T("%s, %llu\n"), FindData.cFileName, MakeQWord( FindData.nFileSizeHigh, FindData.nFileSizeLow));

	}
	while(FindNextFile(hFind, &FindData));
	if(GetLastError() != ERROR_NO_MORE_FILES)
		goto Error;

	// 成功
	res = 0;
Error:
	FindClose(hFind);
	return res;
}

// example
int main()
{
	__uint64  size;
	if(GetDirSize(_T(".\\"), &size))
		printf( "はい失敗\n");

	printf( "%llu\n", size);

	return 0;
}

参考

後から調べたら、同じようなコードを見つけました。見つけてしまいました。

その1

フォルダ内のファイルを再帰的に「列挙する」だけで、「サイズを調べる」わけじゃないですけど。
http://shoppers-jp.com/tech/sdk017.html
http://shoppers-jp.com/tech/sdk006.html

その2

http://www.geocities.jp/dolanpura/free/index.htm
こちらの方は、WIN32_FIND_DATAをちゃんとクラス化してるみたいでした。


もう英語なんかで検索したらいくらでもヒットしそう。