#include"CShell.h"
#include"../CString.h"
#include"../../Template/com_ptr.h"
#include"CRegistry.h"


#include<shlobj.h>
#include<shlwapi.h>
#include<vector>
#include<io.h>
#include<direct.h>
#include<stdio.h>
#include<string>
#define INITGUID
#include<initguid.h>
#include<dxdiag.h>

#pragma comment ( lib, "shell32.lib" )
#pragma comment ( lib, "shlwapi.lib" )
#pragma comment ( lib, "comctl32.lib" )


namespace Maid
{
	namespace CShell
	{

void CoInitialize()
{
	const HRESULT ret = ::CoInitialize( NULL );

	if( FAILED(ret) )
	{
		MAID_THROWEXCEPTION(MAIDTEXT("CoInitialize に失敗"));
	}
}

void CoUninitialize()
{
	::CoUninitialize();
}


void InitCommonControls()
{
	::InitCommonControls();
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 各種システムディレクトリ名の取得
/*!
 	@param	hWnd	[i ]	SHGetSpecialFolderLocation関数が表示するかもしれない
\n							メッセージボックスのオーナーにしたいウィンドウハンドル
 	@param	nFolder	[i ]	調べたい引数 SHGetSpecialFolderLocation のヘルプを参照のこと
 
 	@return	パス名
 */
mstring WinAPI_SHGetSpecialFolderLocation( HWND hWnd, int nFolder )
{
	TCHAR szPath[_MAX_PATH] = {0};
    LPITEMIDLIST pidl;

    IMalloc *pMalloc;
    SHGetMalloc( &pMalloc );

    if( SUCCEEDED(::SHGetSpecialFolderLocation(hWnd,nFolder,&pidl)) )
    { 
        ::SHGetPathFromIDList(pidl,szPath);	 // パスに変換する
        pMalloc->Free(pidl);				 // 取得したIDLを解放する (CoTaskMemFreeでも可)
    }

    pMalloc->Release();

	return CString::ConvertSJIStoMAID(szPath);
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! Program Files ディレクトリを探す
/*!
 	@param	hWnd	[i ]	SHGetSpecialFolderLocation関数が表示するかもしれない
\n							メッセージボックスのオーナーにしたいウィンドウハンドル
 
 	@return	Program Files のパス名
 */
mstring GetProgramFilesFolder( HWND hWnd )
{
/*
	// Windows フォルダを１つ登って program files を見つける
	char buf[MAX_PATH];
	::GetWindowsDirectory( buf, MAX_PATH );

	mstring str = CString::ConvertSJIStoMAID(buf);


	return CString::GetDirectory(str) + L"\\Program Files";
*/
	return WinAPI_SHGetSpecialFolderLocation( hWnd, CSIDL_PROGRAM_FILES );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デスクトップ ディレクトリを探す
/*!
 	@param	hWnd	[i ]	SHGetSpecialFolderLocation関数が表示するかもしれない
\n							メッセージボックスのオーナーにしたいウィンドウハンドル
 
 	@return	デスクトップ のパス名
 */
mstring GetDeskTopFolder( HWND hWnd )
{
	return WinAPI_SHGetSpecialFolderLocation( hWnd, CSIDL_DESKTOPDIRECTORY );
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! Program Menu ディレクトリを探す
/*!
 	@param	hWnd	[i ]	SHGetSpecialFolderLocation関数が表示するかもしれない
\n							メッセージボックスのオーナーにしたいウィンドウハンドル
 
 	@return	Program Menu のパス名
 */
mstring GetProgramMenuFolder( HWND hWnd )
{
	return WinAPI_SHGetSpecialFolderLocation( hWnd, CSIDL_PROGRAMS );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! AppData ディレクトリを探す
/*!
 	@param	hWnd	[i ]	SHGetSpecialFolderLocation関数が表示するかもしれない
\n							メッセージボックスのオーナーにしたいウィンドウハンドル
 
 	@return	Program Menu のパス名
 */
mstring GetApplicationDataFolder( HWND hWnd )
{
	return WinAPI_SHGetSpecialFolderLocation( hWnd, CSIDL_APPDATA );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! MyDocument ディレクトリを探す
/*!
 	@param	hWnd	[i ]	SHGetSpecialFolderLocation関数が表示するかもしれない
\n							メッセージボックスのオーナーにしたいウィンドウハンドル
 
 	@return	Program Menu のパス名
 */
mstring GetMyDocumentsFolder( HWND hWnd )
{
	return WinAPI_SHGetSpecialFolderLocation( hWnd, CSIDL_PERSONAL );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! Windows ディレクトリを探す
/*!
 *	\return	Windows のパス名
 */
mstring GetWindowsFolder()
{
	const UINT len =  ::GetWindowsDirectory( NULL, 0 );

	MySTL::vector<char> Text( len );

	::GetWindowsDirectory( &(Text[0]), len );
	Text.push_back('\0');

	return CString::ConvertSJIStoMAID(&(Text[0]));
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在のカレントディレクトリ名を取得する
/*!
 *	\return	Windows のパス名
 */
mstring GetCurrentDirectory()
{
	char buf[MAX_PATH];
	::GetCurrentDirectory( MAX_PATH, buf );

	return CString::ConvertSJIStoMAID(buf);
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! このプログラムを実行しているexeファイル名を取得する
/*!
 *	\return	Windows のパス名
 */
mstring GetExeFileName()
{
	char szPath[MAX_PATH];
	::GetModuleFileName( NULL, szPath, MAX_PATH );
	return CString::ConvertSJIStoMAID(szPath);
}

void SetCurrentDirectory( const mstring& FilePath )
{
	::SetCurrentDirectory( Maid::CString::ConvertMAIDtoSJIS(FilePath).c_str() );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ショートカットの作成
/*!
 	@param	ShortCutPath	[i ]	作成するショートカットファイル名
 	@param	TargetPath		[i ]	ショートカットを作られる実体のファイル名
 	@param	CommandLine		[i ]	コマンドライン
 
	@exception CException ショートカットの作成に失敗した場合
 */
void CreateShortCut( const mstring& ShortCutPath, const mstring& TargetPath, const mstring& CommandLine )
{
	const MySTL::string sjis_shorcut = CString::ConvertMAIDtoSJIS(ShortCutPath);
	const MySTL::string sjis_target  = CString::ConvertMAIDtoSJIS(TargetPath);
	const MySTL::string sjis_command = CString::ConvertMAIDtoSJIS(CommandLine);

    com_ptr<IShellLink> pShellLink;


	pShellLink.CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink );
    pShellLink->SetPath(sjis_target.c_str());

	if( !CommandLine.empty() )
	{
		const HRESULT ret = pShellLink->SetArguments( sjis_command.c_str() ); 
		if( FAILED(ret) ) { MAID_THROWEXCEPTION(MAIDTEXT("IShellLink->SetArguments()に失敗")); }
	}

	{
		com_ptr<IPersistFile> pPersistFile;

		OLECHAR SCPath[500];    //保存先のパスはUnicode
 		ZERO( SCPath, sizeof(SCPath) );

		::MultiByteToWideChar(CP_ACP, 0, sjis_shorcut.c_str(), -1, SCPath, MAX_PATH );

		pShellLink.QueryInterface(IID_IPersistFile, pPersistFile);

		const HRESULT ret = pPersistFile->Save(SCPath,TRUE);
		if( FAILED(ret) ) { MAID_THROWEXCEPTION(MAIDTEXT("IPersistFile->Save()に失敗")); }
	}
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ディレクトリの作成
/*!
 	階層がある場合でも一括して作成できます
 
 	@param	DirectoryPath	[i ]	作成するディレクトリ名
 
	@exception CException ディレクトリの作成に失敗した場合
 */
void CreateDirectory( const mstring& DirectoryPath )
{
	MySTL::vector<mstring> dat;
	CreateDirectory( DirectoryPath, dat );

/*
	mstring src = DirectoryPath;

	if( src[src.length()-1]!=mstring::CODE_BACKSLASH && src[src.length()-1]!=mstring::CODE_SLASH )
	{
		src += mstring::CODE_BACKSLASH;
	}


	for( int i=0; i<(int)src.length(); ++i )
	{
		const unt32 c = src[i];

		if( c==mstring::CODE_BACKSLASH || c==mstring::CODE_SLASH )
		{
			const mstring m_path = src.substr(0,i);
			const MySTL::string path = CString::ConvertMAIDtoSJIS(m_path);

			if (::access(path.c_str(),0)!=0)
			{
				if (::mkdir(path.c_str())!=0) 
				{
					MAID_THROWEXCEPTION(MAIDTEXT("ディレクトリ") + m_path + MAIDTEXT("の作成に失敗")); 
				}
			}
		}
	}
*/
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ディレクトリの作成
/*!
 	階層がある場合でも一括して作成できます
 
 	param	DirectoryPath	[i ]	作成するディレクトリ名
 	param	CreateList		[ o]	作成したディレクトリ
 
	@exception CException ディレクトリの作成に失敗した場合
 */
void CreateDirectory( const mstring& DirectoryPath, MySTL::vector<mstring>& CreateList )
{
	mstring src = DirectoryPath;

	if( src[src.length()-1]!=mstring::CODE_BACKSLASH && src[src.length()-1]!=mstring::CODE_SLASH )
	{
		src += mstring::CODE_BACKSLASH;
	}


	for( int i=0; i<(int)src.length(); ++i )
	{
		const unt32 c = src[i];

		if( c==mstring::CODE_BACKSLASH || c==mstring::CODE_SLASH )
		{
			const mstring m_path = src.substr(0,i);
			const MySTL::string path = CString::ConvertMAIDtoSJIS(m_path);

			if (::access(path.c_str(),0)!=0)
			{
				if (::mkdir(path.c_str())!=0) 
				{
					MAID_THROWEXCEPTION(MAIDTEXT("ディレクトリ") + m_path + MAIDTEXT("の作成に失敗")); 
				}

				CreateList.push_back(m_path);
			}
		}
	}
}

bool IsExistFile( const mstring& FilePath )
{
	const MySTL::string src = CString::ConvertMAIDtoSJIS(FilePath);

	return ::PathFileExists(src.c_str())!=0;
}

bool IsExistDirectory( const mstring& FilePath )
{
	const MySTL::string src = CString::ConvertMAIDtoSJIS(FilePath);

	return ::PathIsDirectory(src.c_str())!=0;

}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルサイズの取得
/*!
 	\return	ファイルサイズ
 			ファイルが存在しない場合は 0
 */
unt	GetFileSize( const mstring& FilePath )
{
	const MySTL::string path = CString::ConvertMAIDtoSJIS(FilePath);

	unt ret =0;

	HANDLE hFile;
	DWORD  FileSizeHigh;

	hFile = ::CreateFile(
		path.c_str(),
		0,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	ret = ::GetFileSize(hFile, &FileSizeHigh);

	::CloseHandle(hFile);

	return ret;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルのコピー
/*!
 	コピー先にディレクトリがない場合、失敗します
 
 	@param	SrcPath	[i ]	コピー元ファイル名
 	@param	DstPath	[i ]	コピー先ファイル名
 
	@exception CException コピーに失敗した場合
 */
void CopyFile( const mstring& SrcPath, const mstring& DstPath )
{
	const MySTL::string src = CString::ConvertMAIDtoSJIS(SrcPath);
	const MySTL::string dst = CString::ConvertMAIDtoSJIS(DstPath);

	if( ::CopyFile( src.c_str(), dst.c_str(), FALSE )==0 ) 
	{
		MAID_THROWEXCEPTION(SrcPath + MAIDTEXT("->") + DstPath + MAIDTEXT("のコピーに失敗") ); 
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルの削除
/*!
 	@param	FileName	[i ]	削除するファイル名
 
	@exception CException 削除に失敗した場合
 */
void DeleteFile( const mstring& FileName )
{
	const MySTL::string src = CString::ConvertMAIDtoSJIS(FileName);

	if( ::PathFileExists(src.c_str())==0 ) { return ; }

	if( ::DeleteFile(src.c_str())==0 ) 
	{
		MAID_THROWEXCEPTION(FileName + MAIDTEXT("の削除に失敗") ); 
	}
}

void DeleteDirectory( const mstring& DirectoryName )
{
	const MySTL::string src = CString::ConvertMAIDtoSJIS(DirectoryName);
	if( ::PathIsDirectory(src.c_str())==0 ) { return ; }

	if( ::RemoveDirectory(src.c_str())==0 ) 
	{
		MAID_THROWEXCEPTION(DirectoryName + MAIDTEXT("の削除に失敗") ); 
	}
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//!	ユニークな名前を作成する
/*!
 	@return	名前
 */
mstring GenerateUniqueName()
{
	GUID g;
	::CoCreateGuid(&g);

	char buf[256];

	sprintf( buf, "%8x%4x%4x%s", g.Data1, g.Data2, g.Data3, g.Data4 );

	const mstring ret = CString::ConvertSJIStoMAID(buf);

	return ret;
}




/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 直前に呼び出したＡＰＩのエラーコードを文字列化する
/*!
 	@return	エラーメッセージ
 */
mstring GetLastErrorString()
{
	LPVOID pMsgBuf;

	::FormatMessage( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト言語
			(LPTSTR) &pMsgBuf,
			0,
			NULL 

	);

	const mstring str = CString::ConvertSJIStoMAID((char*)pMsgBuf);

	LocalFree( pMsgBuf );

	return str;
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! Windowsの種類を取得する
/*!
 *	\return	Windowsの種類
 */
WINDOWSVERSION	GetWindowsVersion()
{
	OSVERSIONINFO	ver   = { sizeof(OSVERSIONINFO) };
	OSVERSIONINFOEX	verex = { sizeof(OSVERSIONINFOEX) };
	::GetVersionEx( &ver );
	::GetVersionEx( (LPOSVERSIONINFOA)&verex );

	if( ver.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS )
	{
		if( ver.dwMajorVersion==4 )
		{
			switch( ver.dwMinorVersion )
			{
			case  0: { return WINDOWSVERSION_95; }break;
			case 10: { return WINDOWSVERSION_98; }break;
			case 90: { return WINDOWSVERSION_ME; }break;
			}
		}

	}else if( ver.dwPlatformId==VER_PLATFORM_WIN32_NT )
	{
		if( ver.dwMajorVersion==5 )
		{
			switch( ver.dwMinorVersion )
			{
			case 0:
				{
					switch( verex.wProductType )
					{
					case VER_NT_WORKSTATION: { return WINDOWSVERSION_2000_PROFESSIONAL; }
					case VER_NT_SERVER:		 { return WINDOWSVERSION_2000_SERVER; }
					}
				}break;
			case 1:
				{
					if( IsFlag(verex.wSuiteMask,VER_SUITE_PERSONAL) )
					{
						return WINDOWSVERSION_XP_HOME; 
					}else
					{
						switch( verex.wProductType )
						{
						case VER_NT_WORKSTATION: { return WINDOWSVERSION_XP_PROFESSIONAL; }
						case VER_NT_SERVER:		 { return WINDOWSVERSION_XP_DOTNETSERVER; }
						}
					}
				}break;
			}
		}
		ef( ver.dwMajorVersion==6 )
		{
			return WINDOWSVERSION_VISTA;
		}
		ef( ver.dwMajorVersion<5 )
		{
			return WINDOWSVERSION_NT;
		}

	}

	return WINDOWSVERSION_NOTFOUND;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! Windows9X 系であるか？
/*!
 *	\return	9x系であるなら true
 */
bool			IsWindowsVersion9x()
{
	return GetWindowsVersion()<WINDOWSVERSION_NT;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! WindowsNT 系であるか？
/*!
 *	\return	NT系であるなら true
 */
bool			IsWindowsVersionNT()
{
	return !IsWindowsVersion9x();

}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! BrowseForFolder() の内部で呼ばれるコールバックプロシージャ
/*!
 	今のところ最初から選択されているフォルダの設定しかしていない
 
 	@param  hWnd	[i ]	ダイアログボックスのウィンドウハンドル
 	@param  uMsg	[i ]	各種メッセージ
 	@param  lParam	[i ]	メッセージの詳細
 	@param  lpData	[i ]	メッセージの詳細
 
	@return 常に０
 */
int CALLBACK SHBrowseProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
{
	switch( uMsg )
	{
	case BFFM_INITIALIZED:
		{
			if( lpData!=NULL )
			{
				SendMessage( hWnd, BFFM_SETSELECTION, TRUE, lpData);
			}
		}
		break;
	}
 
    return 0;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォルダ選択ダイアログの表示
/*!
 	@param  hWnd			[i ]	親ウィンドウ
 	@param  Title			[i ]	タイトル
 	@param  DefaultFolder	[i ]	最初に選択されている（デフォルトで空文字）
 
	@return 選択したフォルダパス
 			選択しなくても "" が返る
 */
mstring BrowseForFolder( HWND hWnd, const mstring& Title, const mstring& DefaultFolder )
{
	const MySTL::string sjis_lparam = CString::ConvertMAIDtoSJIS(DefaultFolder);
	const MySTL::string sjis_tittle = CString::ConvertMAIDtoSJIS(Title);

	BROWSEINFO  bi;

	ZeroMemory( &bi, sizeof(bi) );
	bi.hwndOwner = hWnd;
	bi.lParam = (LPARAM)sjis_lparam.c_str();
	bi.lpfn   = SHBrowseProc;
	bi.lpszTitle = sjis_tittle.c_str();
	bi.ulFlags   = BIF_RETURNONLYFSDIRS;

	ITEMIDLIST  *lpidlist = ::SHBrowseForFolder(&bi);    // ダイアログ表示
	if( lpidlist==NULL ) { 	return false;  }				//キャンセルを押したとき

	char    buf[MAX_PATH];
	::SHGetPathFromIDList(lpidlist, buf);    // ITEMIDLIST から絶対パスを取得。

	//解放
	IMalloc *lpimalloc;
	::SHGetMalloc(&lpimalloc);
	if( lpimalloc!=NULL )
	{
		lpimalloc->Free(lpidlist);
		lpimalloc->Release();
	}

	return CString::ConvertSJIStoMAID(buf);
}







/*!
 	@class CFindObject CFindObject.h
 	@brief ファイル情報クラス
 */

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 */
CFindObject::CFindObject()
{
	ZERO( &m_FindData, sizeof(m_FindData) );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 	@param	rData	[i ]	初期化情報
 */
CFindObject::CFindObject( WIN32_FIND_DATA& rData )
{
	m_FindData = rData;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 設定されたデータのファイルタイプの取得
/*!
 	@return	FILETYPE を見てください
 */
CFindObject::TYPE CFindObject::GetFileType() const 
{
	const DWORD dwAttribute = m_FindData.dwFileAttributes;

	if( IsFlag(dwAttribute,FILE_ATTRIBUTE_DIRECTORY) )	{ return TYPE_DIRECTORY; }
	if( IsFlag(dwAttribute,FILE_ATTRIBUTE_ARCHIVE)	 )	{ return TYPE_FILE; }
	if( IsFlag(dwAttribute,FILE_ATTRIBUTE_NORMAL)	 )	{ return TYPE_FILE; }

	return TYPE_UNKOWN;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 設定されたデータのファイル名の取得
/*!
 	@return	ファイル名
 */
mstring	CFindObject::GetFileName() const 
{
	return CString::ConvertSJIStoMAID(m_FindData.cFileName);
}



FINDOBJECTLIST PickupFile( const mstring& Path )
{
	return PickupFile( Path, SPPICKUPFILEFILTER( new CPickupFileFilter ) );
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したパターンに合うファイルを抜き出す
/*!
 	@param	Path	[i ]	抜き出したいファイルパターン（ *,? も使用可能）
 	@param	pFilter	[i ]	比較するフィルタ
 
 	@return	抜き出したファイル名リスト

	@exception CException コピーに失敗した場合
 */
FINDOBJECTLIST PickupFile( const mstring& Path, const SPPICKUPFILEFILTER& pFilter )
{
	FINDOBJECTLIST FileList;
	HANDLE hFind;

	WIN32_FIND_DATA	Filedata;
	ZERO( &Filedata, sizeof(Filedata) );

	const MySTL::string sjis_path = CString::ConvertMAIDtoSJIS(Path);


	hFind = ::FindFirstFile( sjis_path.c_str(), &Filedata );
	if( hFind==INVALID_HANDLE_VALUE ) { MAID_THROWEXCEPTION(MAIDTEXT("初期化に失敗")); }

	if( pFilter->IsPassage( CFindObject(Filedata) ) )
	{
		FileList.push_back( Filedata );
	}

	const MySTL::string BeginName = Filedata.cFileName;	//	ほっとくとずっと回ってしまうのでチェック文字を作る
	while( true )
	{
		if( ::FindNextFile( hFind, &Filedata )==0 ) { break; }

		if( pFilter->IsPassage( CFindObject(Filedata) ) )
		{
			FileList.push_back( Filedata );
		}

		if( BeginName==Filedata.cFileName ) { break; }
	}

	::FindClose( hFind );


	return FileList;
}









MySTL::wstring GetValue( const com_ptr<IDxDiagContainer>&	pContainer, const MySTL::wstring& KeyName )
{
	HRESULT ret;
    VARIANT var;

	WCHAR wszPropValue[256];
    VariantInit( &var );

    ret = pContainer->GetProp( KeyName.c_str(), &var );
    if( SUCCEEDED(ret) )
    {
        switch( var.vt )
        {
		case VT_UI4:{ swprintf( wszPropValue, L"%d", var.ulVal );	}break;
		case VT_I4:	{ swprintf( wszPropValue, L"%d", var.lVal );	}break;
		case VT_BOOL:{ swprintf( wszPropValue, L"%s", (var.boolVal) ? L"true" : L"false" );	}break;
        case VT_BSTR:
			{
                wcsncpy( wszPropValue, var.bstrVal, 255 );
                wszPropValue[255] = 0;
			}break;
        }

        VariantClear( &var );
	}

	return wszPropValue;
}

MySTL::wstring GetDxDiagSystemInfo( const com_ptr<IDxDiagContainer>& pDxDiagRoot )
{
	HRESULT ret;
	com_ptr<IDxDiagContainer>	pContainer;
	{
		IDxDiagContainer* p;
		ret = pDxDiagRoot->GetChildContainer( L"DxDiag_SystemInfo", &p );
		if( FAILED(ret) ) { return MySTL::wstring(); }
		pContainer.reset( p );
	}

	MySTL::wstring	str;

	str += L"PhysicalMemory " + GetValue( pContainer, L"ullPhysicalMemory" ) + L"\r\n";
	str += L"UsedPageFile   " + GetValue( pContainer, L"ullUsedPageFile" ) + L"\r\n";
	str += L"AvailPageFile  " + GetValue( pContainer, L"ullAvailPageFile" ) + L"\r\n";

	str += L"ProcessorEnglish          " + GetValue( pContainer, L"szProcessorEnglish" ) + L"\r\n";
	str += L"SystemManufacturerEnglish " + GetValue( pContainer, L"szSystemManufacturerEnglish" ) + L"\r\n";
	str += L"SystemModelEnglish        " + GetValue( pContainer, L"szSystemModelEnglish" ) + L"\r\n";
	str += L"BIOSEnglish               " + GetValue( pContainer, L"szBIOSEnglish" ) + L"\r\n";
	str += L"PhysicalMemoryEnglish     " + GetValue( pContainer, L"szPhysicalMemoryEnglish" ) + L"\r\n";

	return str;
}


MySTL::wstring GetDxDiagDisplayDevices( const com_ptr<IDxDiagContainer>&	pDxDiagRoot )
{
	HRESULT ret;
	com_ptr<IDxDiagContainer>	pContainer;
	{
		IDxDiagContainer* p;
		ret = pDxDiagRoot->GetChildContainer( L"DxDiag_DisplayDevices", &p );
		if( FAILED(ret) ) { return MySTL::wstring(); }
		pContainer.reset( p );
	}

	MySTL::wstring	str;

    DWORD ChildCount;

	ret = pContainer->GetNumberOfChildContainers( &ChildCount );
    if( FAILED(ret) ) { return MySTL::wstring(); }

	for( DWORD i=0; i<ChildCount; ++i )
	{
		WCHAR wszChildName[256];

		ret = pContainer->EnumChildContainerNames( i, wszChildName, 256 );
		if( FAILED(ret) ) { continue; }

		com_ptr<IDxDiagContainer>	pChild;
		{
			IDxDiagContainer* p;
			ret = pContainer->GetChildContainer( wszChildName, &p );
			if( FAILED(ret) ) { continue; }
			pChild.reset( p );
		}

		str += L"   device    \r\n";
		str += L"Description            " + GetValue( pChild, L"szDescription" ) + L"\r\n";
		str += L"Manufacturer           " + GetValue( pChild, L"szManufacturer" ) + L"\r\n";
		str += L"ChipType               " + GetValue( pChild, L"szChipType" ) + L"\r\n";

		str += L"DisplayMemoryLocalized " + GetValue( pChild, L"szDisplayMemoryLocalized" ) + L"\r\n";
		str += L"DisplayMemoryEnglish   " + GetValue( pChild, L"szDisplayMemoryEnglish" ) + L"\r\n";
		str += L"DriverVersion          " + GetValue( pChild, L"szDriverVersion" ) + L"\r\n";
	}

	return str;

}

mstring DeviceCapsStringOut()
{
	mstring		ReturnText;

	try
	{
		{
			OSVERSIONINFO	ver = { sizeof(OSVERSIONINFO) };
			::GetVersionEx( &ver );

			CRegistry	hReg;
			mstring		strData;

			strData += MAIDTEXT("Windows  Caps-------------------------------------------------------------------\r\n");

			//	Win9x系　かWinNT系で キーの位置が違う
			mstring subkey;
			if( ver.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS )
			{
				subkey = MAIDTEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
			}else if( ver.dwPlatformId==VER_PLATFORM_WIN32_NT )
			{
				subkey = MAIDTEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
			}
			
			hReg.Open( CRegistry::KEY_LOCAL_MACHINE, subkey );

			{
				mstring		str;
				hReg.GetValue( MAIDTEXT("ProductName"), str );
				if( !str.empty() )	//	OS名の取得
				{
					strData += str;
					strData += MAIDTEXT("\r\n");
				}
			}

			{
				mstring		str;
				hReg.GetValue( MAIDTEXT("CSDVersion"), str );
				if( !str.empty() )	//	OS名の取得
				{
					strData += str;
					strData += MAIDTEXT("\r\n");
				}
			}

			//	ビルド番号、バージョンの取得
			char	mess[256];
			sprintf( mess, "Bulid %d Ver %d.%d\r\n", ver.dwBuildNumber<3000?ver.dwBuildNumber:0, ver.dwMajorVersion, ver.dwMinorVersion );
			strData += CString::ConvertSJIStoMAID(mess);


			//	DirectX のバージョンの取得
			hReg.Open( CRegistry::KEY_LOCAL_MACHINE, MAIDTEXT("SOFTWARE\\Microsoft\\DirectX") );

			{
				mstring		str;
				hReg.GetValue( MAIDTEXT("Version"), str );

				if( !str.empty() )
				{
					strData += MAIDTEXT("DirectX Ver ");
					strData += str;
					strData += MAIDTEXT("\r\n");
				}
			}

			ReturnText += strData;
		}
		{
			MySTL::wstring		strData;
			//	dxdiag から拾える情報を拾う
			//	
			com_ptr<IDxDiagProvider>	pDxDiagProvider;
			com_ptr<IDxDiagContainer>	pDxDiagRoot;


			pDxDiagProvider.CoCreateInstance( CLSID_DxDiagProvider, NULL, CLSCTX_INPROC_SERVER, IID_IDxDiagProvider );

			{
				// Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize
				// Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are 
				// digital signed as logo'd by WHQL which may connect via internet to update 
				// WHQL certificates.    
				DXDIAG_INIT_PARAMS dxDiagInitParam;
				ZeroMemory( &dxDiagInitParam, sizeof(DXDIAG_INIT_PARAMS) );

				dxDiagInitParam.dwSize                  = sizeof(DXDIAG_INIT_PARAMS);
				dxDiagInitParam.dwDxDiagHeaderVersion   = DXDIAG_DX9_SDK_VERSION;
				// WHQLを確認するかどうか
				// ネットを経由するので基本的にはfalseにしておく
				dxDiagInitParam.bAllowWHQLChecks        = false;
				dxDiagInitParam.pReserved               = NULL;

				HRESULT		ret;
				ret = pDxDiagProvider->Initialize( &dxDiagInitParam );
				if( FAILED(ret) ) { MAID_THROWEXCEPTION(MAIDTEXT("IDxDiagProvider::Initialize") ); }

				{
					IDxDiagContainer* p;
					ret = pDxDiagProvider->GetRootContainer( &p );
					if( FAILED(ret) ) {	MAID_THROWEXCEPTION(MAIDTEXT("IDxDiagContainer::GetRootContainer") ); }

					pDxDiagRoot.reset( p );
				}

				/*

					必要な項目の以下のとおり
					ここに書いてあるのだけ拾ってくる
					文字列はすべて unicode になっているので注意

				DxDiag_SystemInfo.ullPhysicalMemory = 536330240
				DxDiag_SystemInfo.ullUsedPageFile = 236158976
				DxDiag_SystemInfo.ullAvailPageFile = 1072644096

				DxDiag_SystemInfo.szProcessorEnglish = AMD Athlon(tm) Processor,  MMX,  3DNow, ~1.3GHz
				DxDiag_SystemInfo.szSystemManufacturerEnglish = VIA
				DxDiag_SystemInfo.szSystemModelEnglish = 7VRX                            
				DxDiag_SystemInfo.szBIOSEnglish = Default System BIOS
				DxDiag_SystemInfo.szPhysicalMemoryEnglish = 512MB RAM

				DxDiag_DisplayDevices.0.szDescription = Xabre
				DxDiag_DisplayDevices.0.szManufacturer = SiS
				DxDiag_DisplayDevices.0.szChipType = Xabre  80 Rev 01
				DxDiag_DisplayDevices.0.szDisplayMemoryLocalized = 64.0 MB
				DxDiag_DisplayDevices.0.szDisplayMemoryEnglish = 64.0 MB
				DxDiag_DisplayDevices.0.szDriverVersion = 6.14.0010.3530

				*/

				{
					strData += GetDxDiagSystemInfo( pDxDiagRoot );
					strData += GetDxDiagDisplayDevices( pDxDiagRoot );
				}
			}

			MySTL::vector<char> ret;
			{
				const int len = ::WideCharToMultiByte(CP_THREAD_ACP,0,strData.c_str(),-1,NULL,0,NULL,NULL);
				if( 0<len )
				{
					ret.resize(len);
					::WideCharToMultiByte(CP_THREAD_ACP,0,strData.c_str(),-1, &ret[0],len,NULL,NULL);
					ret.push_back( '\0' );
				}
			}

			ReturnText += CString::ConvertSJIStoMAID( &ret[0] );
		}
	}catch(...)	{}

	if( ReturnText.empty() ) { ReturnText = MAIDTEXT("Unkwon"); }

	return ReturnText;
}




	}
}