Diff

Not logged in

Differences From Artifact [f1f9b8362f0839ce]:

To Artifact [bcd83037acfbb1eb]:


> 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 }