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 }