
/** @file
    @brief		システムクラス
    @author		Noriyuki Lee
    @since		2003.07.01
		@note
		改造、脆弱性フィックス　:
		d金魚

		
*/
#include "stdafx.h"
#include "dkutilFunction01.h"
#include "dkutilDefined.h"

//#include "dkutilFunction02.h"
//#include "dKingyoUtilClass.h"
//#include "dKingyoMacro.h"


// for文スコープ強制準拠マクロ
#define for						if ( false ) ; else for	
//bad_alloc



namespace dkutil{

/*
<PRE>
		☆CDのボリュームラベル検索

		任意のボリュームラベルを持つＣＤを検索します。
</PRE>

@param		char *pLabel	: 検索するボリュームラベル
@param		char *pPath		: 検索対象のボリュームラベルを持つドライブの格納先

@return		bool			: 成功 true / 失敗 false
*/



/*
<PRE>
		☆壁紙設定

		壁紙を設定します。
</PRE>

@param		char *pFile		: 壁紙に設定するファイル名
@param		long Type		: 0 中央に表示 / 1 並べて表示 / 2 画面サイズに合わせて拡大表示
@param		bool IsReboot	: 再起動後に有効にする場合 true

@return bool			: 成功 true / 失敗 false
*/
bool SetWallPaper( char *pFile, long Type, bool IsReboot )
{
	//===================================================
	// 壁紙設定
	//===================================================
	HKEY hkey = NULL;
	unsigned char key0[2] = { '0' };
	unsigned char key1[2] = { '1' };
	unsigned char key2[2] = { '2' };

	//---------------------------------------------
	// レジストリ書き換え
	//---------------------------------------------
	::RegOpenKey( HKEY_CURRENT_USER, "Control Panel\\desktop\\", &hkey );
	// ファイルパス
	::RegSetValueEx( hkey, "Wallpaper", 0, REG_SZ, (unsigned char*)pFile, strlen(pFile) );
	// 表示モード
	switch ( Type )
	{
	case 0:
		::RegSetValueEx( hkey, "TileWallpaper",  0, REG_SZ, key0, 1 );
		::RegSetValueEx( hkey, "WallpaperStyle", 0, REG_SZ, key0, 1 );
		break;
	case 1:
		::RegSetValueEx( hkey, "TileWallpaper",  0, REG_SZ, key1, 1 );
		::RegSetValueEx( hkey, "WallpaperStyle", 0, REG_SZ, key0, 1 );
		break;
	case 2:
		::RegSetValueEx( hkey, "TileWallpaper",  0, REG_SZ, key0, 1 );
		::RegSetValueEx( hkey, "WallpaperStyle", 0, REG_SZ, key2, 1 );
		break;
	}
	::RegCloseKey( hkey );

	//---------------------------------------------
	// 壁紙変更
	//---------------------------------------------
	if ( !IsReboot )
	{
		::SystemParametersInfo(
					SPI_SETDESKWALLPAPER,
					NULL,
					pFile,
					SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
	}

	return true;
}


/*
	@param	char *pDir		: ディレクトリ名
	@param	char *pAppName	: アプリケーション名
	@return 成功 true / 失敗 false
*/
bool RunApplication( char *pDir, char *pAppName )
{
	char temp[MAX_PATH] = "";
	_snprintf( temp, MAX_PATH, "%s%s", pDir, pAppName );

	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi = {0};

	int r = ::CreateProcess(
					temp,
					NULL,
					NULL,
					NULL,
					false,
					NORMAL_PRIORITY_CLASS,
					NULL,
					pDir,
					&si,
					&pi );
	return (r != 0);
}


/*

		☆ブラウザ起動

		ブラウザ起動を起動し任意のURLのサイトを開きます。
		フォルダのパスを与えるとフォルダを開くこともできます。

	input
		char *pURL		: 開くURL


*/

bool OpenBrowser( char *pURL )
{
	//Returns a value greater than 32 if successful
#ifdef USE_DKINGYO_SHELL_AND_COMMON_CONTROL
	return (32 < (ULONG)::ShellExecute( NULL, "open", pURL, NULL, NULL, SW_SHOW ));
#else
	return OpenExplorer(pURL);
#endif
}


/*

		☆ウィンドウズディレクトリ取得

		ウィンドウズのディレクトリを取得します。

	input
		char *Dir	: 	ウィンドウズのsディレクトリパス格納先

	output


void GetWindowsDir( char *pDir )
{
	char path[MAX_PATH] = "";
	::GetWindowsDirectory( path, MAX_PATH );

	strncpy( pDir, path ,MAX_PATH);
}
*/

/*

		☆ファイルコピー

		ファイルコピーを行います。
		ファイル属性が通常になりますので、
		CDからコピーされた場合は読取専用が
		解除されます。

	input
		char *pSrc	: コピー元
		char *pDst	: コピー先

	output
		bool			: 成功 true / 失敗 false


bool CopyFile( char *pSrc, char *pDst )
{
//	 コピー
    if ( ::CopyFile( pSrc, pDst, false ) )
	{
		// ファイル属性を通常にする
        return (::SetFileAttributes( pDst, FILE_ATTRIBUTE_NORMAL ) != false);
    }

    return false;
}
*/

/*

		☆ファイル削除

		ファイル削除を行います。

	input
		char *pSrc	: 削除元

	output


void DeleteFile( char *pSrc )
{
	remove( pSrc );
}
*/

/*
		☆ファイルサイズ取得
		ファイルサイズを取得します。
@param		char *pSrc	: 取得元
@return  filesize

dGetFileSizeの方が優秀。
なぜならロックされたファイルでもサイズを得ることができるから。

unsigned long GetFileSize( char *pSrc )
{
	unsigned long size = 0;

	 //ファイルサイズ取得
	HANDLE hFile = ::CreateFile(
						pSrc,
						GENERIC_READ,
						FILE_SHARE_READ,
						NULL,
						OPEN_EXISTING,
						FILE_ATTRIBUTE_NORMAL,
						NULL );
	if ( hFile != INVALID_HANDLE_VALUE )
	{
		size += ::GetFileSize( hFile, NULL );
		::CloseHandle( hFile );
	}

	return size;
}
*/


/*

		☆フォルダ選択ダイアログ

		フォルダ選択ダイアログをだします。

	input
		char *pDir		: ディレクトリ格納先

	output
		bool	: 成功 true / 失敗 false
*/
/*
bool FolderSelect( char *pDir ,HWND WindowHandle)
{
	pDir[0] = '\0';

  HRESULT hr;
  BROWSEINFO bi;
  ITEMIDLIST *lpid = NULL;
  LPMALLOC pMalloc = NULL;

	ZeroMemory( &bi, sizeof(BROWSEINFO) );

	bi.hwndOwner	= WindowHandle;
	bi.ulFlags		= BIF_EDITBOX;
	bi.lpszTitle	= "ディレクトリ指定";

	lpid = ::SHBrowseForFolder( &bi );

	if ( lpid == NULL )
	{
		return false;
	}
	else
	{
		hr = ::SHGetMalloc( &pMalloc );
		if ( hr == E_FAIL )
		{
			MessageBox(WindowHandle,  "SHGetMalloc Error", "Error",MB_OK);
			return false;
		}

		::SHGetPathFromIDList( lpid, pDir );
		if ( pDir[strlen(pDir) - 1] != '\\' ) strcat( pDir, "\\" );

		pMalloc->Free( lpid );
		pMalloc->Release();
	}

	//Luna::ResetCurrentDirectory();

	return true;
}
*/









/*
		☆ファイル存在チェック

		ファイルの存在チェックをします。

	input
		char *pFile		: チェックするファイル名

	output
*/




/*
		☆フォルダ生成

		フォルダの生成をします。

	input
		char *pPath		: 生成フォルダパス

	output
		bool	: 成功 true / 失敗 false

*/



/*
		☆メモリサイズ取得

		物理メモリのサイズを取得します。

	input
		unsigned long *pTotalMem	: 合計メモリ容量を格納するポインタ
		unsigned long *pFreeMem		: 空きメモリ容量を格納するポインタ

	output

*/
void GetMemorySize( unsigned long *pTotalMem, unsigned long *pFreeMem )
{
	MEMORYSTATUS memstate = { sizeof( memstate ) };
	::GlobalMemoryStatus( &memstate );

	if ( pTotalMem != NULL ) *pTotalMem = memstate.dwTotalPhys;
	if ( pFreeMem != NULL ) *pFreeMem = memstate.dwAvailPhys;
}


/*
		☆カラー選択ダイアログ

		カラー選択ダイアログを開き色の取得をします。

	input
		long *pR	: 赤色格納先アドレス
		long *pG	: 緑色格納先アドレス
		long *pB	: 青色格納先アドレス

	output
		bool		: 成功 true / 失敗 false
*/

bool OpenColorDialog( long *pR, long *pG, long *pB ,HWND WindowHandle)
{
	COLORREF color = RGB(*pR,*pG,*pB);

	CHOOSECOLOR cc = {
		sizeof(CHOOSECOLOR),
		WindowHandle,
		NULL,
		color,
		&color,
		CC_FULLOPEN,
	};

	if ( !::ChooseColor( &cc ) ) return false;

	*pR = (cc.rgbResult>>16) & 0xFF;
	*pG = (cc.rgbResult>> 8) & 0xFF;
	*pB = (cc.rgbResult>> 0) & 0xFF;

	return true;
}


/*
		☆ローカル時間取得

		現在地の時間を取得します。

	input
		long *pYear			: 西暦を受け取る変数のアドレス
		long *pMonth		: 月を受け取る変数のアドレス
		long *pWeekDay		: 曜日を受け取る変数のアドレス
		long *pDay			: 日を受け取る変数のアドレス
		long *pHour			: 時を受け取る変数のアドレス
		long *pMinute		: 分を受け取る変数のアドレス
		long *pSecond		: 秒を受け取る変数のアドレス
		long *pMilliSecond	: ミリ秒を受け取る変数のアドレス

	output
		bool		: 成功 true / 失敗 false

*/
void GetLocalTime( long *pYear, long *pMonth, long *pWeekDay, long *pDay, long *pHour, long *pMinute, long *pSecond, long *pMilliSecond )
{
	SYSTEMTIME SystemTime;
	memset( &SystemTime, 0x00, sizeof(SYSTEMTIME) );
	::GetLocalTime( &SystemTime );

	if ( pYear			!= NULL ) *pYear		= SystemTime.wYear;
	if ( pMonth			!= NULL ) *pMonth		= SystemTime.wMonth;
	if ( pDay			!= NULL ) *pDay			= SystemTime.wDay;
	if ( pWeekDay		!= NULL ) *pWeekDay		= SystemTime.wDayOfWeek;
	if ( pHour			!= NULL ) *pHour		= SystemTime.wHour;
	if ( pMinute		!= NULL ) *pMinute		= SystemTime.wMinute;
	if ( pSecond		!= NULL ) *pSecond		= SystemTime.wSecond;
	if ( pMilliSecond	!= NULL ) *pMilliSecond	= SystemTime.wMilliseconds;
}


/*
		☆１ヶ月の日数を取得

		１ヶ月の日数を取得します。

	input
		long year	: 年
		long month	: 月

	output
		long		: １ヶ月の日数
*/

long DayOfMonth( long year, long month )
{
	static const long days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

	if ( month == 2 )
	{
		if ( (year%400 == 0) || ((year%4 == 0) && (year%100 != 0) ) )
		{
			return days[1] + 1;
		}
	}

	return days[month-1];
}

/*

		☆月始めの曜日取得

		月始めの曜日を取得します。

@param		long year	: 年
@param		long month	: 月

@return		long		: 月初めの曜日
*/
long DayOfWeek( long year, long month )
{
	long i;
	long day = 0, week = 0;

	for ( i = 1; i < month; i++ )
	{
		day = day + DayOfMonth( year, i );
	}

	week = day + (year * 365) + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400);

	return (week % 7);
}


/*
<PRE>

		文字コード取得

	与えられた文字の文字コードを取得します

</PRE>

@param		*pKey			: キーデータ格納先
@param		KeyNo		: 調べるキー番号
*/
void KeyCheck( dkutilKeyState *pKey, unsigned long KeyNo )
{
	//------------------------------------------------------------
	// キー押されてるよ
	//------------------------------------------------------------
	if ( (::GetKeyState( KeyNo ) & 0x80) == 0x80 )
	{
		switch ( *pKey )
		{
		case DKUTIL_KEY_STATE_FREE:
		case DKUTIL_KEY_STATE_PULL:
			*pKey = DKUTIL_KEY_STATE_PUSH;
			break;

		case DKUTIL_KEY_STATE_PUSH:
		case DKUTIL_KEY_STATE_HOLD:
			*pKey = DKUTIL_KEY_STATE_HOLD;
			break;
		}
	}
	//------------------------------------------------------------
	// キー押されてないよ
	//------------------------------------------------------------
	else
	{
		switch ( *pKey )
		{
		case DKUTIL_KEY_STATE_FREE:
		case DKUTIL_KEY_STATE_PULL:
			*pKey = DKUTIL_KEY_STATE_FREE;
			break;

		case DKUTIL_KEY_STATE_PUSH:
		case DKUTIL_KEY_STATE_HOLD:
			*pKey = DKUTIL_KEY_STATE_PULL;
			break;
		}
	}
}



void ChangeEndian( void *pData, unsigned long Bytes )
{
	switch ( Bytes )
	{
	case 2:
		{
			char Temp[] = {
				*((char *)pData + 1),
				*((char *)pData + 0),
			};
			MoveMemory(pData,Temp,2);
			//::CopyMemory(pData,Temp,2);
			//MemoryCopy( pData, Temp, 2 );
		}
		break;
	case 4:
		{
			char Temp[] = {
				*((char *)pData + 3),
				*((char *)pData + 2),
				*((char *)pData + 1),
				*((char *)pData + 0),
			};
			MoveMemory(pData,Temp,4);
			//::CopyMemory(pData,Temp,4);
			//MemoryCopy( pData, Temp, 4 );
		}
		break;
	case 8:
		{
			char Temp[] = {
				*((char *)pData + 7),
				*((char *)pData + 6),
				*((char *)pData + 5),
				*((char *)pData + 4),
				*((char *)pData + 3),
				*((char *)pData + 2),
				*((char *)pData + 1),
				*((char *)pData + 0),
			};
			MoveMemory(pData,Temp,8);
			//::CopyMemory( pData, Temp, 8 );
			//MemoryCopy( pData, Temp, 8 );
		}
		break;
	}
}

#ifdef USE_DKINGYO_OBJECT_TEST
void TestLunaSystem(){

	char path[MAX_PATH];
	//ヴォリュームラヴェル検索
	if(CheckVolumeLabel( "dKingyo", path ,sizeof(path)))
	{
		MB("ボリュームラベル検索　SUCCESSED");
	}else{
		MB("ボリュームラベル検索 FAILED");
		std::string s="CheckVolumeLabel関数は例えば、\n";
		s+="商用ソフト等でソフトのCDが入っていないとでき内容にする時に使える。\n";
		s+="ボリュームラベルはタブン、\n";
		s+="CD-ROMドライブにCDを入れたとき表示される名前のことだと思う。\n";

		MB(const_cast<char *>(s.c_str()));
	}
	//壁紙チェンジ
	if(SetWallPaper( "dKingyoWallpaper.bmp", 2, false ))
	{
		MB("壁紙設定OK");
	}else{
		MB("壁紙設定FAILED");
	}

	if(RunApplication( "allocate_speed_test/", "allocate_test_release.exe" ))
	{
		MB("RunApplication OK");
	}else{
		MB("RunApplication FAILED");
	}

	MB("d金魚のホームページを起動します。");
	//ブラウザ起動
	OpenBrowser( "http://NihongoURL.nu/止水" );


	::memset(path,0,sizeof(path));
	GetWindowsDir( path );
	dOutputDebugString("Windows path is = %s",path);



	//ファイルコピー
	char *dest = "allocate_test_release2.exe";

	if(CopyFile( "allocate_speed_test/allocate_test_release.exe",dest  ))
	{
		ODS("CopyFile SUCCEEDED\n");
	}else{
		MB("CopyFile FAILED");
	}


	//☆ファイル削除
	DeleteFile( dest );


	char *data = "暗号化データです。";
	size_t datasize = strlen(data) + 1;
	char *savename = "Encoded.bin";
	if(SaveData( savename,(void *)data, datasize  ))
	{
		dOutputDebugString("暗号化して保存するデータ文字列は[ %s ]です。ファイル名は[%s]です。"
			,data,savename);
		ODS("暗号化保存OK\n");
	}else{
		MB("SaveData FAILED");
	}




	char data_a[MAX_PATH];
	::memset(data_a,0,sizeof(data_a));
	if(LoadData( savename, (void *)data_a,datasize  ))
	{
		ODS("暗号化読み出しOK 内容は -> ");
		dOutputDebugString(data_a);
	}else{
		MB("LoadData FAILED");
	}


	//folder select
	/*
	::memset(path,0,sizeof(path));
	if(FolderSelect( path ,NULL))
	{
		ODS("FolderSelect is ");
		dOutputDebugString(path);
	}else{
		MB("FolderSelect FAILED");
	}*/

	//オープン用ダイアログ
	::memset(path,0,sizeof(path));
	if(FileOpenDialog( path , "FileOpenDialog Function Test" , 
				"text(*.txt)\0*.txt\0dKingyo is Programmer(*.*)\0*.*\0\0", "txt" ,NULL)
				){
		dOutputDebugString("open path is = %s",path);
	}else{
		MB("FAILED");
	}


	
	//セーブ用ダイアログ
	::memset(path,0,sizeof(path));
	if(FileSaveDialog( 
			path, "FileSaveDialog Function Test", 
			"text(*.txt)\0*.txt\0dKingyo is Programmer(*.*)\0*.*\0\0", "d金魚" ,
			NULL)
			){
		dOutputDebugString("save path is = %s",path);
	}else{
		MB("FAILED");
	}

	
	/*if(CreateLinkFile( char *pShortcutFile, char *pDescription, char *pTargetFile ))
	{

	}else{
		MB("ERROR");
	}*/


	//get desktop folder
	/*
	::memset(path,0,sizeof(path));
	if(GetDesktopFolder( path ))
	{
		ODS("Desktop folder path is ");
		dOutputDebugString(path);
	}


	SetShowIME( true);
	*/

	char *str = "dkutilSoftware.h";
	if(FileExist( str ))
	{
		ERROR_BOX("%s fileは存在します。",str);
	}
	char *created_folder_name="dKingyoUtilClass Beta";
	str = created_folder_name;

	if(CreateDirectory( str ))
	{
		ERROR_BOX("%s ディレクトリを生成しました。",str);
	}



	//get memory size 
	ULONG TotalMem,FreeMem;
	GetMemorySize(&TotalMem, &FreeMem );
	dOutputDebugString("TotalMem=%d,FreeMem=%d",TotalMem,FreeMem);

	//RGB color dialog
	long R,G,B;
	OpenColorDialog( &R, &G, &B ,NULL);
	dOutputDebugString("R=%d,G=%d,B=%d",R,G,B);

	//オリンピックの年を試してみる
	dOutputDebugString("うるう年(オリンピック年)2月=%d",DayOfMonth( 2000, 2 ));

		//2000年問題を試してみる
	dOutputDebugString("月初めの月曜日 = %d",DayOfWeek( 2000, 1 ));


	dkutilKeyState state;
	KeyCheck( &state, VK_F1 );

	//change endian
	int endian = 0xffff0000;
	dOutputDebugString("before = %x \n change endian...",endian);
	ChangeEndian( (void *)&endian, sizeof(endian) );
	dOutputDebugString("after = %x",endian);

	//後始末
	RemoveDirectory(created_folder_name);

}
#else
void TestLunaSystem(){
	//英語に自信なし･･･
	ODS("Please turn on USE_DKINGYO_OBJECT_TEST defined\n");
}
#endif


}//end of dkutil namespace

#undef for

