Differences From Artifact [f1f9b8362f0839ce]:
- File
src/qbga32.d
- 2011-02-23 12:53:16 - part of checkin [c2b7a98c21] on branch trunk - Initial import (user: kinaba) [annotate]
To Artifact [bcd83037acfbb1eb]:
- File
src/qbga32.d
- 2015-04-21 10:46:55 - part of checkin [4e2933c620] on branch trunk - Rebased to the latest verson dmd 2.067. Not yet verified the outcome. (user: kinaba) [annotate]
> 1 private import core.sys.windows.dll;
> 2 private import win32.windows;
> 3 private import win32.winuser;
1 private import std.string; 4 private import std.string;
2 private import std.file; 5 private import std.file;
3 private import win32.ansi.windows; <
4 private import util; 6 private import util;
5 private import windll; 7 private import windll;
6 private import bga_melter; 8 private import bga_melter;
7 private import qbga_gui; 9 private import qbga_gui;
8 10
9 //---------------------------------------------------------------- 11 //----------------------------------------------------------------
10 // おきまりのDLL初期化ルーチン 12 // おきまりのDLL初期化ルーチン
11 //---------------------------------------------------------------- 13 //----------------------------------------------------------------
12 14
13 HINSTANCE g_hinst; | 15 __gshared HINSTANCE g_hinst;
14 <
15 extern(C) <
16 { <
17 void gc_init(); <
18 void gc_term(); <
19 void _minit(); <
20 void _moduleCtor(); <
21 void _moduleDtor(); <
22 void _moduleUnitTests(); <
23 } <
24 16
25 extern (Windows) 17 extern (Windows)
26 BOOL DllMain( HINSTANCE inst, ULONG reason, void* reserved ) 18 BOOL DllMain( HINSTANCE inst, ULONG reason, void* reserved )
27 { 19 {
28 switch( reason ) 20 switch( reason )
29 { 21 {
30 case DLL_PROCESS_ATTACH: 22 case DLL_PROCESS_ATTACH:
31 g_hinst = inst; 23 g_hinst = inst;
32 gc_init(); // GC初期化 | 24 dll_process_attach( inst, true );
33 _minit(); // モジュールリスト初期化 <
34 _moduleCtor(); // モジュールコンストラクタ実行 <
35 _moduleUnitTests(); // 単体テスト実行 <
36 if( g_orig_dll is null ) 25 if( g_orig_dll is null )
37 return false; 26 return false;
38 break; 27 break;
39 28
40 case DLL_PROCESS_DETACH: 29 case DLL_PROCESS_DETACH:
41 _moduleDtor(); | 30 dll_process_detach( inst, true );
42 gc_term(); // GC終了 | 31 break;
> 32
> 33 case DLL_THREAD_ATTACH:
> 34 dll_thread_attach( true, true );
> 35 break;
> 36
> 37 case DLL_THREAD_DETACH:
> 38 dll_thread_detach( true, true );
43 break; 39 break;
44 40
45 default: 41 default:
46 case DLL_THREAD_ATTACH: <
47 case DLL_THREAD_DETACH: <
48 break; <
49 } 42 }
50 return true; 43 return true;
51 } 44 }
52 45
53 //---------------------------------------------------------------- 46 //----------------------------------------------------------------
54 // API転送処理 47 // API転送処理
55 //---------------------------------------------------------------- 48 //----------------------------------------------------------------
56 49
57 WinDLL g_orig_dll = null; | 50 __gshared WinDLL g_orig_dll = null;
58 UINT WM_ARCEXTRACT; | 51 __gshared UINT WM_ARCEXTRACT;
59 52
60 static this() 53 static this()
61 { 54 {
62 g_orig_dll = WinDLL.load( "_Bga32.DLL" ); 55 g_orig_dll = WinDLL.load( "_Bga32.DLL" );
63 WM_ARCEXTRACT = RegisterWindowMessage("wm_arcextract"); 56 WM_ARCEXTRACT = RegisterWindowMessage("wm_arcextract");
64 } 57 }
65 58
................................................................................................................................................................................
66 static ~this() 59 static ~this()
67 { 60 {
68 g_orig_dll.close(); 61 g_orig_dll.close();
69 } 62 }
70 63
71 template api(FnT) 64 template api(FnT)
72 { 65 {
73 FnT api( char[] name ) | 66 FnT api( string name )
74 { 67 {
75 return g_orig_dll.get_api!(FnT)( name ); 68 return g_orig_dll.get_api!(FnT)( name );
76 } 69 }
77 } 70 }
78 71
79 //---------------------------------------------------------------- 72 //----------------------------------------------------------------
80 // 統合アーカイバAPI:転送 73 // 統合アーカイバAPI:転送
81 //---------------------------------------------------------------- 74 //----------------------------------------------------------------
82 75
83 extern(Windows) 76 extern(Windows)
84 { 77 {
85 int Bga( HWND a, char* b, char* c, DWORD d ) | 78 int Bga( HWND a, immutable char* b, char* c, DWORD d )
86 { 79 {
87 int r = Bga_impl( a, toString(b) ); | 80 int r = Bga_impl( a, b.fromStringz() );
88 if( r < 0 ) // このダミーDLLでは処理できないコマンドだった時 81 if( r < 0 ) // このダミーDLLでは処理できないコマンドだった時
89 return api!(typeof(&Bga))("Bga")(a,b,c,d); 82 return api!(typeof(&Bga))("Bga")(a,b,c,d);
90 return r; 83 return r;
91 } 84 }
92 85
93 WORD QBgaGetVersion() 86 WORD QBgaGetVersion()
94 { 87 {
................................................................................................................................................................................
203 } 196 }
204 } 197 }
205 198
206 //---------------------------------------------------------------- 199 //----------------------------------------------------------------
207 // 統合アーカイバAPI:実装( Bga ) 200 // 統合アーカイバAPI:実装( Bga )
208 //---------------------------------------------------------------- 201 //----------------------------------------------------------------
209 202
210 int Bga_impl( HWND wnd, char[] cmd_str ) | 203 int Bga_impl( HWND wnd, string cmd_str )
211 { 204 {
212 enum { UNSUPPORTED = -1 } 205 enum { UNSUPPORTED = -1 }
213 206
214 // 207 //
215 // コマンドライン解析 208 // コマンドライン解析
216 // 209 //
217 char[][] cmd = cmd_parse(cmd_str); | 210 string[] cmd = cmd_parse(cmd_str);
218 211
219 // x以外のコマンドは扱わないで本物DLLに回します。注意点として: 212 // x以外のコマンドは扱わないで本物DLLに回します。注意点として:
220 // > command はコマンドラインの最初の引数としてください。なお、command を省略 213 // > command はコマンドラインの最初の引数としてください。なお、command を省略
221 // > した場合は 'x' command が指定されたものとみなします。 214 // > した場合は 'x' command が指定されたものとみなします。
222 if( cmd.length == 0 ) 215 if( cmd.length == 0 )
223 return UNSUPPORTED; 216 return UNSUPPORTED;
224 if( cmd[0].length == 1 ) 217 if( cmd[0].length == 1 )
225 { 218 {
226 if( 0 <= find("adjlmnstvADJLMNSTV", cmd[0][0]) ) | 219 if( 0 <= "adjlmnstvADJLMNSTV".indexOf(cmd[0][0]) )
227 return UNSUPPORTED; 220 return UNSUPPORTED;
228 if( cmd[0][0]=='x' || cmd[0][0]=='X' ) 221 if( cmd[0][0]=='x' || cmd[0][0]=='X' )
229 cmd = cmd[1 .. length]; | 222 cmd = cmd[1 .. $];
230 } 223 }
231 224
232 // ※ この時点で、cmdにはcommandを除いた残りの引数が入っているはず | 225 // ※ この時点で、cmdにはcommandを除いた残りの引数が入っているはず
233 226
234 // 227 //
235 // スイッチ解析、引数解析 228 // スイッチ解析、引数解析
236 // 229 //
237 bool all_attrs = false; // -a 230 bool all_attrs = false; // -a
238 bool silent = false; // -i 231 bool silent = false; // -i
239 bool ignore_dir = false; // -j 232 bool ignore_dir = false; // -j
240 bool newfile_only = false; // -n 233 bool newfile_only = false; // -n
241 bool force_overwrite = false; // -o 234 bool force_overwrite = false; // -o
242 bool recursive = false; // -r 235 bool recursive = false; // -r
243 bool sanitize_path = true; 236 bool sanitize_path = true;
244 237
245 char[] arc_name = null; | 238 string arc_name = null;
246 char[] base_dir = null; | 239 string base_dir = null;
247 char[][] paths; | 240 string[] paths;
248 241
249 foreach( char[] param ; cmd ) | 242 foreach( string param ; cmd )
250 if( param[0] == '-' ) 243 if( param[0] == '-' )
251 switch( param[1] ) 244 switch( param[1] )
252 { 245 {
253 case 'a','A': all_attrs = true; break; 246 case 'a','A': all_attrs = true; break;
254 case 'i','I': silent = true; break; 247 case 'i','I': silent = true; break;
255 case 'j','J': ignore_dir = true; break; 248 case 'j','J': ignore_dir = true; break;
256 case 'n','N': newfile_only = true; break; 249 case 'n','N': newfile_only = true; break;
................................................................................................................................................................................
263 arc_name = param; 256 arc_name = param;
264 } 257 }
265 else if( base_dir is null ) 258 else if( base_dir is null )
266 { 259 {
267 if( lastChar(param) == '\\' ) 260 if( lastChar(param) == '\\' )
268 base_dir = param; 261 base_dir = param;
269 else { 262 else {
> 263 char[] buf;
270 base_dir.length = GetCurrentDirectory(0,null)+1; | 264 buf.length = GetCurrentDirectoryA(0,null)+1;
271 GetCurrentDirectory(base_dir.length, base_dir); | 265 GetCurrentDirectoryA(buf.length, buf.ptr);
272 base_dir.length = strlen(base_dir); <
> 266 base_dir = buf.ptr.fromStringz().idup;
273 if( lastChar(base_dir) != '\\' ) 267 if( lastChar(base_dir) != '\\' )
274 base_dir ~= '\\'; 268 base_dir ~= '\\';
275 } 269 }
276 } 270 }
277 else 271 else
278 paths ~= param; 272 paths ~= param;
279 273
................................................................................................................................................................................
289 if( !silent && g_handler is null ) // -i / OwnerWndProc 283 if( !silent && g_handler is null ) // -i / OwnerWndProc
290 { 284 {
291 dlg = new ProgressDlg( 285 dlg = new ProgressDlg(
292 cast(DLGTEMPLATE*) g_orig_dll.load_dialog("#2025 286 cast(DLGTEMPLATE*) g_orig_dll.load_dialog("#2025
293 dlg.set_arcname(arc_name); 287 dlg.set_arcname(arc_name);
294 } 288 }
295 289
296 char[] src_fname; // OwnerWndProc関係 | 290 string src_fname; // OwnerWndProc関係
297 BgaHeader cur_hdr; // OwnerWndProc関係 291 BgaHeader cur_hdr; // OwnerWndProc関係
298 292
299 BgaAnswer handler( inout BgaHeader hdr ) | 293 BgaAnswer handler( ref BgaHeader hdr )
300 { 294 {
301 src_fname = hdr.fname; 295 src_fname = hdr.fname;
302 process_messages(); 296 process_messages();
303 297
304 // paths 298 // paths
305 if( paths.length > 0 ) 299 if( paths.length > 0 )
306 { 300 {
307 char[] fname = // -r | 301 string fname = // -r
308 (recursive ? hdr.fname[hdr.dir_name_len. | 302 (recursive ? hdr.fname[hdr.dir_name_len.
309 : hdr.fname); <
310 foreach( char[] w ; paths ) | 303 foreach( string w ; paths )
311 if( wild_match( w, fname ) ) 304 if( wild_match( w, fname ) )
312 goto ok; 305 goto ok;
313 return BgaAnswer.SkipIt; 306 return BgaAnswer.SkipIt;
314 ok:; 307 ok:;
315 } 308 }
316 // -a 309 // -a
317 if( !all_attrs && (hdr.attrib&6) ) 310 if( !all_attrs && (hdr.attrib&6) )
318 return BgaAnswer.SkipIt; 311 return BgaAnswer.SkipIt;
319 // dialog 312 // dialog
320 if( dlg ) 313 if( dlg )
321 if( dlg.closed ) 314 if( dlg.closed )
322 return BgaAnswer.Abort; 315 return BgaAnswer.Abort;
323 else 316 else
324 dlg.set_filename( hdr.fname[hdr.dir_name | 317 dlg.set_filename( hdr.fname[hdr.dir_name
325 // -j 318 // -j
326 if( ignore_dir ) 319 if( ignore_dir )
327 hdr.fname = hdr.fname[hdr.dir_name_len .. length | 320 hdr.fname = hdr.fname[hdr.dir_name_len .. $];
328 // sanitize 321 // sanitize
329 if( sanitize_path ) 322 if( sanitize_path )
330 hdr.fname = check_path(hdr.fname); 323 hdr.fname = check_path(hdr.fname);
331 // base_dir 324 // base_dir
332 hdr.fname = base_dir ~ hdr.fname; | 325 hdr.fname = (base_dir ~ hdr.fname).dup;
333 // -o 326 // -o
334 if( !force_overwrite ) 327 if( !force_overwrite )
335 try { 328 try {
336 if( std.file.exists(hdr.fname) && std.file.isfil | 329 if( std.file.exists(hdr.fname) && std.file.isFil
337 // -n 330 // -n
338 if( newfile_only ) 331 if( newfile_only )
339 { 332 {
340 if( newer_than(hdr.date,hdr.time 333 if( newer_than(hdr.date,hdr.time
341 return BgaAnswer.SkipIt; 334 return BgaAnswer.SkipIt;
342 } 335 }
343 else 336 else
344 { 337 {
345 int r = MessageBox( dlg?dlg.hwnd | 338 int r = MessageBoxA( dlg?dlg.hwn
346 toStringz("Overwrite "~h 339 toStringz("Overwrite "~h
347 "QBga32.dll", MB_YESNOCA 340 "QBga32.dll", MB_YESNOCA
348 if( r == IDNO ) return BgaAn 341 if( r == IDNO ) return BgaAn
349 if( r == IDCANCEL ) return BgaAn 342 if( r == IDCANCEL ) return BgaAn
350 } 343 }
351 } catch {} 344 } catch {}
352 345
................................................................................................................................................................................
410 char szMode[8]; 403 char szMode[8];
411 } 404 }
412 405
413 HWND g_owner_window; 406 HWND g_owner_window;
414 extern(Windows) BOOL function(HWND,UINT,UINT,EXTRACTINGINFOEX*) g_handler; 407 extern(Windows) BOOL function(HWND,UINT,UINT,EXTRACTINGINFOEX*) g_handler;
415 extern(Windows) BOOL noex_handler( HWND w,UINT m,UINT s, EXTRACTINGINFOEX* e ) 408 extern(Windows) BOOL noex_handler( HWND w,UINT m,UINT s, EXTRACTINGINFOEX* e )
416 { 409 {
417 return !SendMessage( w, m, s, cast(LPARAM) &e.exinfo ); | 410 return !SendMessageA( w, m, s, cast(LPARAM) &e.exinfo );
418 } 411 }
419 412
420 void BgaSetOwnerWindow_impl( HWND wnd ) 413 void BgaSetOwnerWindow_impl( HWND wnd )
421 { 414 {
422 g_owner_window = wnd; 415 g_owner_window = wnd;
423 g_handler = &noex_handler; 416 g_handler = &noex_handler;
424 } 417 }
................................................................................................................................................................................
432 void BgaSetOwnerWindowEx_impl( HWND wnd, ARCHIVERPROC* proc ) 425 void BgaSetOwnerWindowEx_impl( HWND wnd, ARCHIVERPROC* proc )
433 { 426 {
434 g_owner_window = wnd; 427 g_owner_window = wnd;
435 g_handler = *proc; 428 g_handler = *proc;
436 } 429 }
437 430
438 enum { OP_FILE_BEGIN, OP_FILE_MIDDLE, OP_ARC_END, OP_ARC_BEGIN } 431 enum { OP_FILE_BEGIN, OP_FILE_MIDDLE, OP_ARC_END, OP_ARC_BEGIN }
439 bool do_ownerwnd_proc( UINT uState, BgaHeader* hdr, int cur, char[] src_fname ) | 432 bool do_ownerwnd_proc( UINT uState, BgaHeader* hdr, int cur, string src_fname )
440 { 433 {
441 if( g_handler is null ) 434 if( g_handler is null )
442 return true; 435 return true;
443 EXTRACTINGINFOEX ex; 436 EXTRACTINGINFOEX ex;
444 if( uState == OP_ARC_BEGIN || uState == OP_ARC_END ) 437 if( uState == OP_ARC_BEGIN || uState == OP_ARC_END )
445 { 438 {
446 lstrcpyn( ex.exinfo.szSourceFileName, toStringz(src_fname), 512 | 439 lstrcpynA( ex.exinfo.szSourceFileName.ptr, toStringz(src_fname),
447 } 440 }
448 else 441 else
449 { 442 {
450 ex.exinfo.dwFileSize = hdr.original_size; 443 ex.exinfo.dwFileSize = hdr.original_size;
451 ex.exinfo.dwWriteSize = cur; 444 ex.exinfo.dwWriteSize = cur;
452 lstrcpyn( ex.exinfo.szSourceFileName, toStringz(src_fname), 512 | 445 lstrcpynA( ex.exinfo.szSourceFileName.ptr, toStringz(src_fname),
453 lstrcpyn( ex.exinfo.szDestFileName, toStringz(hdr.fname), 512 ); | 446 lstrcpynA( ex.exinfo.szDestFileName.ptr, toStringz(hdr.fname), 5
454 ex.dwCompressedSize = hdr.compressed_size; 447 ex.dwCompressedSize = hdr.compressed_size;
455 ex.wRatio = cast(int)( (cast(real)hdr.compressed_size)/hdr.origi | 448 ex.wRatio = cast(ushort)( (cast(real)hdr.compressed_size)/hdr.or
456 ex.wDate = hdr.date; 449 ex.wDate = hdr.date;
457 ex.wTime = hdr.time; 450 ex.wTime = hdr.time;
458 ex.szAttribute[0] = (hdr.attrib&32 ? 'A': '-'); 451 ex.szAttribute[0] = (hdr.attrib&32 ? 'A': '-');
459 ex.szAttribute[1] = (hdr.attrib&1 ? 'R': '-'); 452 ex.szAttribute[1] = (hdr.attrib&1 ? 'R': '-');
460 ex.szAttribute[2] = (hdr.attrib&2 ? 'H': '-'); 453 ex.szAttribute[2] = (hdr.attrib&2 ? 'H': '-');
461 ex.szAttribute[3] = (hdr.attrib&4 ? 'S': '-'); 454 ex.szAttribute[3] = (hdr.attrib&4 ? 'S': '-');
462 ex.szAttribute[4] = (hdr.attrib&16 ? 'D': '-'); 455 ex.szAttribute[4] = (hdr.attrib&16 ? 'D': '-');
463 ex.szAttribute[5] = '\0'; 456 ex.szAttribute[5] = '\0';
464 if( hdr.method[0]=='G' ) 457 if( hdr.method[0]=='G' )
465 lstrcpy(ex.szMode,"-gzip-"); | 458 lstrcpyA(ex.szMode.ptr,"-gzip-");
466 else 459 else
467 lstrcpy(ex.szMode,"-bzip2-"); | 460 lstrcpyA(ex.szMode.ptr,"-bzip2-");
468 } 461 }
469 462
470 return false != g_handler( g_owner_window, WM_ARCEXTRACT, uState, &ex ); 463 return false != g_handler( g_owner_window, WM_ARCEXTRACT, uState, &ex );
471 } 464 }
472 465
473 //---------------------------------------------------------------- 466 //----------------------------------------------------------------
474 // パス検査系 467 // パス検査系
475 //---------------------------------------------------------------- 468 //----------------------------------------------------------------
476 469
477 alias std.c.windows.windows.IsDBCSLeadByte isDL; | 470 alias core.sys.windows.windows.IsDBCSLeadByte isDL;
478 char[] replace_yen( char[] s ) | 471 string replace_yen( string s )
479 { 472 {
480 char[] ans; | 473 string ans;
481 int j=0; 474 int j=0;
482 for(int i=0; i!=s.length; i=i+(isDL(s[i])?2:1)) 475 for(int i=0; i!=s.length; i=i+(isDL(s[i])?2:1))
483 if( s[i] == '\\' ) 476 if( s[i] == '\\' )
484 ans~=s[j .. i], ans~='/', j=i+1; 477 ans~=s[j .. i], ans~='/', j=i+1;
485 ans ~= s[j .. length]; | 478 ans ~= s[j .. $];
486 return ans; 479 return ans;
487 } 480 }
488 481
489 bool wild_match( char[] wild, char[] name ) | 482 bool wild_match( string wild, string name )
490 { 483 {
491 bool wild_match_nopath( char[] w, char[] s ) | 484 bool wild_match_nopath( string w, string s )
492 { 485 {
493 char[] advance( char[] s ) | 486 string advance( string s )
494 { 487 {
495 return s[(IsDBCSLeadByte(s[0])?2:1) .. length]; | 488 return s[(IsDBCSLeadByte(s[0])?2:1) .. $];
496 } 489 }
497 490
498 while( w.length>0 ) 491 while( w.length>0 )
499 switch( w[0] ) 492 switch( w[0] )
500 { 493 {
501 case '?': 494 case '?':
502 if( s.length==0 ) 495 if( s.length==0 )
................................................................................................................................................................................
527 } 520 }
528 return s.length==0; 521 return s.length==0;
529 } 522 }
530 523
531 if( wild=="" || wild=="*.*" || wild=="*" || wild=="**" ) 524 if( wild=="" || wild=="*.*" || wild=="*" || wild=="**" )
532 return true; 525 return true;
533 526
534 char[][] wilds = split( replace_yen( tolower(wild) ), "/" ); | 527 string[] wilds = split( replace_yen( toLower(wild) ), "/" );
535 char[][] names = split( replace_yen( tolower(name) ), "/" ); | 528 string[] names = split( replace_yen( toLower(name) ), "/" );
536 529
537 if( wilds.length != names.length ) 530 if( wilds.length != names.length )
538 return false; 531 return false;
539 for(int i=0; i!=wilds.length; ++i) 532 for(int i=0; i!=wilds.length; ++i)
540 if( wilds[i]!="*.*" && wilds[i]!="*" && wilds[i]!="**" ) 533 if( wilds[i]!="*.*" && wilds[i]!="*" && wilds[i]!="**" )
541 if( !wild_match_nopath( wilds[i], names[i] ) ) 534 if( !wild_match_nopath( wilds[i], names[i] ) )
542 return false; 535 return false;
543 return true; 536 return true;
544 } 537 }
545 538
546 char[] check_path( char[] path ) | 539 string check_path( string in_path )
547 { 540 {
> 541 char[] path = in_path.dup;
> 542
548 // C:\ ==> C_\ 543 // C:\ ==> C_\
549 if( path.length>=2 && path[1]==':' ) 544 if( path.length>=2 && path[1]==':' )
550 path = path.dup, path[1] = '_'; | 545 path[1] = '_';
551 546
552 // \\hoge ==> hoge 547 // \\hoge ==> hoge
553 // /hoge ==> hoge 548 // /hoge ==> hoge
554 while( path.length>0 && (path[0]=='\\'||path[0]=='/') ) 549 while( path.length>0 && (path[0]=='\\'||path[0]=='/') )
555 path = path[1..length]; | 550 path = path[1..$];
556 551
557 // .. ==> __ 552 // .. ==> __
558 char[][] paths = split( replace_yen(path), "/" ); | 553 string[] paths = split( replace_yen(path.idup), "/" );
559 L1: 554 L1:
560 foreach( inout char[] pc ; paths ) | 555 foreach( ref string pc ; paths )
561 if( pc.length >= 2 ) 556 if( pc.length >= 2 )
562 { 557 {
563 foreach( char c ; pc ) 558 foreach( char c ; pc )
564 if( c != '.' ) 559 if( c != '.' )
565 continue L1; 560 continue L1;
566 pc = replace( pc, ".", "_" ); 561 pc = replace( pc, ".", "_" );
567 } 562 }