Artifact Content

Not logged in

Artifact a3b52f0446b0f2d0f3c0c559bc683794f5f52c57


     1  // Noah.cpp
     2  // -- entrypoint etc for 'Noah'
     3  
     4  #include "stdafx.h"
     5  #include "NoahApp.h"
     6  #include "resource.h"
     7  
     8  #if _MSC_VER >= 1300
     9  extern "C" { int _afxForceEXCLUDE; }
    10  extern "C" BOOL WINAPI _imp__IsDebuggerPresent() { return FALSE; }
    11  #endif
    12  
    13  // プロセス個数制限ゾーン
    14  class ProcessNumLimitZone
    15  {
    16  	HANDLE m_han;
    17  public:
    18  	ProcessNumLimitZone(int Max, const char* name)
    19  		: m_han( ::CreateSemaphore( NULL, Max, Max, name ) )
    20  	{
    21  		if( m_han )
    22  			::WaitForSingleObject( m_han, INFINITE );
    23  		else
    24  			kiSUtil::msgLastError("CreateSemaphore Failed");
    25  	}
    26  	~ProcessNumLimitZone()
    27  	{
    28  		if( m_han )
    29  		{
    30  			::ReleaseSemaphore( m_han, 1, NULL );
    31  			::CloseHandle( m_han );
    32  		}
    33  	}
    34  };
    35  
    36  //----------------------------------------------//
    37  //--------- Noah のエントリポイント ------------//
    38  //----------------------------------------------//
    39  
    40  void kilib_create_new_app()
    41  {
    42  	//-- kilib にアプリケーションを設定
    43  	new CNoahApp;
    44  }
    45  
    46  void CNoahApp::run( kiCmdParser& cmd )
    47  {
    48  	//-- 初期化
    49  	m_cnfMan.init();
    50  	m_arcMan.init();
    51  
    52  	//-- コマンドラインパラメータ保持
    53  	m_pCmd = &cmd;
    54  
    55  	//-- 「ファイル名が渡されてない or Shift押し起動」なら設定画面表示
    56  	if( cmd.param().len()==0 || keyPushed(VK_SHIFT) )
    57  	{
    58  		//-- Load-INI ( 全部 )
    59  		m_cnfMan.load( All );
    60  		//-- 設定画面表示
    61  		m_cnfMan.dialog();
    62  	}
    63  	else
    64  	{
    65  		//-- 圧縮解凍などの作業
    66  		do_cmdline( true );
    67  	}
    68  
    69  	//-- 終了処理
    70  	m_tmpDir.remove();
    71  }
    72  
    73  //----------------------------------------------//
    74  //------------- 圧縮/解凍 の 作業 --------------//
    75  //----------------------------------------------//
    76  
    77  bool CNoahApp::is_writable_dir( const kiPath& path )
    78  {
    79  	// 要するに、CDROM/DVDROM を切りたい。
    80  	// FDD, PacketWriteなDisk を切るのはあきらめる。
    81  
    82  	// RAMDISK, REMOTE, FIXED, UNKNOWN なディスクは書き込み可能と見なす
    83  	UINT drv = path.getDriveType();
    84  	if( drv==DRIVE_REMOVABLE || drv==DRIVE_CDROM )
    85  	{
    86  		// 素Win95では使えない関数なのでDynamicLoad
    87  		typedef BOOL (WINAPI*pGDFSE)( LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER );
    88  		pGDFSE pGetDiskFreeSpaceEx
    89  			= (pGDFSE) ::GetProcAddress( ::GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA" );
    90  		if( pGetDiskFreeSpaceEx )
    91  		{
    92  			// 空き容量が0なら、書き込み不可とみなす
    93  			ULARGE_INTEGER fs, dummy;
    94  			pGetDiskFreeSpaceEx( path, &dummy, &dummy, &fs );
    95  			if( fs.QuadPart == 0 )
    96  				return false;
    97  		}
    98  	}
    99  	return true;
   100  }
   101  
   102  void CNoahApp::do_cmdline( bool directcall )
   103  {
   104  	do_files( m_pCmd->param(), &m_pCmd->option(), !directcall );
   105  }
   106  
   107  void CNoahApp::do_files( const cCharArray& files,
   108  						 const cCharArray* opts,
   109  						 bool  basicaly_ignore )
   110  {
   111  	struct local {
   112  		~local() {kiSUtil::switchCurDirToExeDir(); } // ディレクトリロックしないように
   113  	} _;
   114  
   115  	//-- Archiver Manager にファイル名リストを記憶する
   116  	if( 0 == m_arcMan.set_files( files ) )
   117  		return;
   118  
   119  	//-- 作業用変数
   120  	enum { unknown, melt, compress }
   121  			whattodo = unknown;
   122  	bool	ctrl_mlt = keyPushed( VK_CONTROL );
   123  	bool	ctrl_cmp = ctrl_mlt;
   124  	bool	alt      = keyPushed( VK_MENU ) || keyPushed( VK_RWIN ) || keyPushed( VK_LWIN );
   125  	const char *cmptype=NULL, *method=NULL;
   126  	kiPath  destdir;
   127  	kiStr tmp(300);
   128  
   129  	//-- ( もしあれば )コマンドラインオプションを解釈
   130  	if( opts )
   131  		for( unsigned int i=0; i!=opts->len(); i++ )
   132  			switch( (*opts)[i][1] )
   133  			{
   134  			case 'a':	if( !basicaly_ignore )
   135  			case 'A':		whattodo = compress;	break;
   136  
   137  			case 'x':	if( !basicaly_ignore )
   138  			case 'X':		whattodo = melt;		break;
   139  
   140  			case 'd':	if( !basicaly_ignore )
   141  			case 'D':		destdir = (*opts)[i]+2;	break;
   142  
   143  			case 'w':	if( !basicaly_ignore )
   144  			case 'W':		alt = true;				break;
   145  
   146  			case 't':	if( !basicaly_ignore )
   147  			case 'T':		cmptype = (*opts)[i]+2;	break;
   148  
   149  			case 'm':	if( !basicaly_ignore )
   150  			case 'M':		method = (*opts)[i]+2;	break;
   151  
   152  			case 'c':	if( !basicaly_ignore ) {
   153  			case 'C':		if((*opts)[i][2]!='x') ctrl_cmp = true;
   154  							if((*opts)[i][2]!='a') ctrl_mlt = true;
   155  						break;}
   156  			}
   157  
   158  	//-- Load-INI ( 動作モード設定 )
   159  	m_cnfMan.load( Mode );
   160  
   161  	//-- 圧縮解凍のどちらを行うか決定する。流れは以下の通り。
   162  	//
   163  	// ・コマンドラインで、圧縮と指定されてれば無条件で圧縮へ
   164  	//
   165  	// ・そうでなければ、まずNoahの動作モード取得
   166  	//  m0:圧縮専用  m1:圧縮優先  m2:解凍優先  m3:解凍専用
   167  	//   コマンドラインで解凍と指定されていれば m3。
   168  	//   指定が無ければ、m_cnfMan から読み込み。
   169  	//
   170  	// ・m0 か、'm1でしかもファイルが複数' の時は無条件で圧縮へ
   171  	//
   172  	// ・そうでなければ、解凍ルーチンを割り当ててみる。
   173  	//  この際、m3 以外のときは一個でも割り当て失敗したらエラー>圧縮へ
   174  	//  m3 でも、一個も割り当てられなければエラー。>処理終了
   175  
   176  	if( whattodo != compress )
   177  	{
   178  		int mode = 3;
   179  		if( whattodo != melt )
   180  			mode = m_cnfMan.mode();
   181  
   182  		if( mode==0 || ( mode==1 && m_arcMan.file_num()>=2 ) )
   183  			whattodo = compress;
   184  		else
   185  		{
   186  			//-- 解凍ルーチン割り当ててみる
   187  			bool suc = m_arcMan.map_melters( mode );
   188  			if( suc )
   189  				whattodo = melt;
   190  			else
   191  			{
   192  				if( mode != 3 )
   193  					whattodo = compress;
   194  				else
   195  				{
   196  					//-- 解凍専用モードだけど解凍不可!!
   197  					msgBox( tmp.loadRsrc(IDS_M_ERROR) );
   198  					return;
   199  				}
   200  			}
   201  		}
   202  	}
   203  
   204  	if( whattodo == melt )
   205  	{
   206  		//-- 解凍設定は既にm_cnfMan.init()でロードされている…
   207  
   208  		if( destdir.len()==0 )
   209  		{
   210  			//-- 解凍先ディレクトリ取得
   211  			if( m_cnfMan.mdirsm() )
   212  				if( is_writable_dir(m_arcMan.get_basepath()) )
   213  					destdir = m_arcMan.get_basepath();
   214  			if( destdir.len()==0 )
   215  				destdir = m_cnfMan.mdir();
   216  		}
   217  
   218  		//-- 解凍
   219  		if( ctrl_mlt )	m_arcMan.do_listing( destdir );
   220  		else {
   221  			ProcessNumLimitZone zone( mycnf().multiboot_limit(), "LimitterForNoahAtKmonosNet" );
   222  			m_arcMan.do_melting( destdir );
   223  		}
   224  	}
   225  	else
   226  	{
   227  		//-- Load-INI( 圧縮設定 )
   228  		m_cnfMan.load( Compress );
   229  
   230  		if( destdir.len()==0 )
   231  		{
   232  			//-- 圧縮先ディレクトリ取得
   233  			if( m_cnfMan.cdirsm() )
   234  				if( is_writable_dir(m_arcMan.get_basepath()) )
   235  					destdir = m_arcMan.get_basepath();
   236  			if( destdir.len()==0 )
   237  				destdir = m_cnfMan.cdir();
   238  		}
   239  		if( !cmptype ) cmptype = m_cnfMan.cext();
   240  		else if( !method ) method = "";
   241  		if( !method  ) method  = m_cnfMan.cmhd();
   242  
   243  		//-- 圧縮用ルーチンを割り当て
   244  		if( !m_arcMan.map_compressor( cmptype, method, ctrl_cmp ) )
   245  		{
   246  			//-- 圧縮不能な形式!!
   247  			msgBox( tmp.loadRsrc(IDS_C_ERROR) );
   248  			return;
   249  		}
   250  
   251  		//-- 圧縮
   252  		ProcessNumLimitZone zone( mycnf().multiboot_limit(), "LimitterForNoahAtKmonosNet" );
   253  		m_arcMan.do_compressing( destdir, alt );
   254  	}
   255  }
   256  
   257  //----------------------------------------------//
   258  //----------------- その他雑用 -----------------//
   259  //----------------------------------------------//
   260  
   261  // from= 0:normal 1:melt 2:compress
   262  void CNoahApp::open_folder( const kiPath& path, int from )
   263  {
   264  	if( from==1 || from==2 ) //-- Shellに更新通知
   265  		::SHChangeNotify( SHCNE_UPDATEDIR, SHCNF_PATH, (const void*)(const char*)path, NULL );
   266  
   267  	//-- デスクトップだったら開かない
   268  	kiPath dir(path), tmp(kiPath::Dsk,false);
   269  	dir.beBackSlash(false), dir.beShortPath(), tmp.beShortPath();
   270  
   271  	if( !tmp.isSame( dir ) )
   272  	{
   273  		//-- Load-INI( フォルダ開き設定 )
   274  		m_cnfMan.load( OpenDir );
   275  		if( (from==1 && !m_cnfMan.modir())
   276  		 || (from==2 && !m_cnfMan.codir()) )
   277  			return;
   278  		
   279  		char cmdline[1000];
   280  		wsprintf( cmdline, m_cnfMan.openby(), (const char*)dir );
   281  		::WinExec( cmdline, SW_SHOWDEFAULT );
   282  	}
   283  }
   284  
   285  // 全システム中で一意なテンポラリフォルダを作って返す
   286  void CNoahApp::get_tempdir( kiPath& tmp )
   287  {
   288  	char buf[MAX_PATH];
   289  
   290  	if( m_tmpDir.len()==0 )
   291  	{
   292  		::GetTempFileName( kiPath( kiPath::Tmp ), "noa", 0, buf );
   293  		::DeleteFile( buf );
   294  		m_tmpDir = buf;
   295  		m_tmpDir.beBackSlash( true );
   296  		m_tmpDir.mkdir();
   297  		m_tmpID = ::GetCurrentProcessId();
   298  	}
   299  
   300  	::GetTempFileName( m_tmpDir, "noa", m_tmpID++, buf );
   301  	::DeleteFile( buf );
   302  	tmp = buf;
   303  	tmp.beBackSlash( true );
   304  	tmp.mkdir();
   305  }