Subversion Repositories Kolibri OS

Rev

Rev 1122 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;
  2. ; project name:         KFar_Arc - plugin for KFar, which supports various archives
  3. ; target platform:      KolibriOS
  4. ; compiler:             FASM 1.67.14
  5. ; version:              0.17
  6. ; last update:          2009-09-03 (Sep 03, 2009)
  7. ; minimal KFar version: 0.43
  8. ; minimal kernel:       no limit
  9. ;
  10. ; author:               Diamond
  11. ; email:                diamondz@land.ru
  12. ; web:                  http://diamond.kolibrios.org
  13. ;
  14.  
  15. ; standard start of Kolibri dynamic library
  16. format MS COFF
  17. public EXPORTS
  18.  
  19. section '.flat' code readable align 16
  20.  
  21. ; include auxiliary procedures
  22. include 'kglobals.inc'          ; iglobal/uglobal
  23. include 'lang.inc'              ; define language for localized strings
  24. include 'crc.inc'               ; CRC32 calculation
  25. include 'sha256.inc'            ; SHA-256 hash algorithm
  26. include 'aes.inc'               ; AES crypto algorithm
  27. ; include main code for archives loading
  28. include '7z.inc'                ; *.7z
  29. include 'lzma.inc'              ; LZMA-decoder for *.7z
  30. include 'ppmd.inc'              ; PPMD-decoder for *.7z
  31. include '7zbranch.inc'          ; branch filters for *.7z
  32. include '7zaes.inc'             ; AES cryptor for *.7z
  33. include 'zip.inc'               ; *.zip
  34. include 'deflate.inc'           ; Deflate[64] decoder for *.7z and *.zip
  35.  
  36. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  37. ;;;;;;;;;;;;;;; Interface for KFar ;;;;;;;;;;;;;;
  38. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  39. virtual at 0
  40. kfar_info_struc:
  41. .lStructSize    dd      ?
  42. .kfar_ver       dd      ?
  43. .open           dd      ?
  44. .open2          dd      ?
  45. .read           dd      ?
  46. .write          dd      ?
  47. .seek           dd      ?
  48. .tell           dd      ?
  49. .flush          dd      ?
  50. .filesize       dd      ?
  51. .close          dd      ?
  52. .pgalloc        dd      ?
  53. .pgrealloc      dd      ?
  54. .pgfree         dd      ?
  55. .getfreemem     dd      ?
  56. .pgalloc2       dd      ?
  57. .pgrealloc2     dd      ?
  58. .pgfree2        dd      ?
  59. .menu           dd      ?
  60. .menu_centered_in dd    ?
  61. .DialogBox      dd      ?
  62. .SayErr         dd      ?
  63. .Message        dd      ?
  64. .cur_console_size dd    ?
  65. end virtual
  66.  
  67. ; int __stdcall plugin_load(kfar_info* info);
  68. ; Initialization of plugin + Save used KFar functions.
  69. plugin_load:
  70.         mov     eax, [esp+4]
  71.         mov     [kfar_info], eax
  72.         push    [eax+kfar_info_struc.open2]
  73.         pop     [open2]
  74.         push    [eax+kfar_info_struc.filesize]
  75.         pop     [filesize]
  76.         push    [eax+kfar_info_struc.read]
  77.         pop     [read]
  78.         push    [eax+kfar_info_struc.seek]
  79.         pop     [seek]
  80.         push    [eax+kfar_info_struc.close]
  81.         pop     [close]
  82.         lea     esi, [eax+kfar_info_struc.DialogBox]
  83.         mov     edi, DialogBox
  84.         movsd
  85.         movsd
  86.         movsd
  87.         movsd
  88.         lea     esi, [eax+kfar_info_struc.pgalloc]
  89.         mov     edi, pgalloc
  90.         movsd
  91.         movsd
  92.         movsd
  93.         movsd
  94.         call    init_crc_table
  95.         call    init_aes
  96.         call    init_ppmd
  97.         xor     eax, eax        ; success
  98.         ret     4
  99.  
  100. ; HANDLE __stdcall OpenFilePlugin(HANDLE basefile,
  101. ;       const void* attr, const void* data, int datasize,
  102. ;       int baseplugin_id, HANDLE baseplugin_instance, const char* name);
  103. ; This function is called when user presses Enter (or Ctrl+PgDn) on file.
  104. ; Plugin tests whether given file is of supported type
  105. ;   and if so, loads information and returns
  106. ;   handle to be used in subsequent calls to ReadFolder, SetFolder and so on.
  107. OpenFilePlugin:
  108.         mov     [bPasswordDefined], 0
  109.         mov     esi, [esp+12]
  110.         mov     ebp, [esp+4]
  111. ; test for 7z archive
  112.         cmp     dword [esp+16], 20h     ; minimal size of 7z archive is 20h bytes
  113.         jb      .no_7z
  114.         cmp     word [esi], '7z'                ; signature, part 1
  115.         jnz     .no_7z
  116.         cmp     dword [esi+2], 0x1C27AFBC       ; signature, part 2
  117.         jnz     .no_7z
  118.         call    open_7z
  119.         ret     28
  120. .no_7z:
  121. ; test for zip archive
  122.         cmp     dword [esp+16], 22      ; minimal size of zip archive is 22 bytes
  123.         jb      .no_zip
  124.         cmp     word [esi], 0x4B50
  125.         jnz     .no_zip
  126.         cmp     word [esi+2], 0x0403
  127.         jz      .zip
  128.         cmp     word [esi+2], 0x0201
  129.         jz      .zip
  130.         cmp     word [esi+2], 0x0606
  131.         jz      .zip
  132.         cmp     word [esi+2], 0x0706
  133.         jz      .zip
  134.         cmp     word [esi+2], 0x0605
  135.         jnz     .no_zip
  136. .zip:
  137.         call    open_zip
  138.         ret     28
  139. .no_zip:
  140.         xor     eax, eax
  141.         ret     28
  142.  
  143. ; Handle of plugin in kfar_arc is as follow:
  144. virtual at 0
  145. handle_common:
  146. .type           dd      ?
  147. .root.subfolders        dd      ?
  148. .root.subfolders.end    dd      ?
  149. .root.subfiles          dd      ?
  150. .root.subfiles.end      dd      ?
  151. .root.NumSubItems       dd      ?
  152. .curdir                 dd      ?
  153. .NumFiles               dd      ?
  154. ; ... some plugin-specific data follows ...
  155. end virtual
  156.  
  157. ; and for each archive item there is one file info structure, which begins as follow:
  158. virtual at 0
  159. file_common:
  160. .fullname       dd      ?       ; pointer to cp866 string
  161. .name           dd      ?       ; name without path (end of .fullname)
  162. .namelen        dd      ?       ; strlen(.name)
  163. .bIsDirectory   db      ?
  164. .bPseudoFolder  db      ?
  165.                 rb      2
  166. .parent         dd      ?       ; pointer to parent directory record
  167. .subfolders     dd      ?       ; head of L2-list of subfolders [for folders]
  168. .subfolders.end dd      ?
  169. .subfiles       dd      ?       ; head of L2-list of files [for folders]
  170. .subfiles.end   dd      ?
  171. .NumSubItems    dd      ?
  172. .next           dd      ?       ; next item in list of subfolders/files
  173. .prev           dd      ?       ; previous item in list of subfolders/files
  174. .stamp          dd      ?       ; stamp for GetFiles
  175. end virtual
  176.  
  177. ; void __stdcall ClosePlugin(HANDLE hPlugin);
  178. ; This function frees all resources allocated in OpenFilePlugin.
  179. ClosePlugin:
  180.         mov     eax, [esp+4]    ; get hPlugin
  181.         mov     eax, [eax]      ; hPlugin is pointer to internal data structure
  182.                                 ; first dword is archive type (type_xxx constants)
  183.         dec     eax             ; types start from 1
  184.         jmp     dword [ClosePluginTable+eax*4]
  185.  
  186. ; int __stdcall ReadFolder(HANDLE hPlugin,
  187. ;       unsigned dirinfo_start, unsigned dirinfo_size, void* dirdata);
  188. ReadFolder:
  189. ; init header
  190.         mov     edi, [esp+16]
  191.         mov     ecx, 32/4
  192.         xor     eax, eax
  193.         rep     stosd
  194.         mov     byte [edi-32], 1        ; version
  195.         mov     ebp, [esp+4]
  196. ; get current directory
  197.         lea     ebx, [ebp+handle_common.root.subfolders]
  198.         cmp     [ebp+handle_common.curdir], 0
  199.         jz      @f
  200.         mov     ebx, [ebp+handle_common.curdir]
  201.         add     ebx, file_common.subfolders
  202. @@:
  203.         mov     ecx, [ebx+16]
  204.         mov     [edi-24], ecx           ; number of files
  205. ; edi points to BDFE
  206.         push    6               ; assume EOF
  207.         pop     eax
  208.         sub     ecx, [esp+8]
  209.         ja      @f
  210.         and     dword [edi-28], 0       ; number of files read
  211.         ret     10h
  212. @@:
  213.         cmp     ecx, [esp+12]
  214.         jb      @f
  215.         mov     ecx, [esp+12]
  216.         xor     eax, eax        ; OK
  217. @@:
  218.         mov     [edi-28], ecx
  219.         push    eax
  220. ; copy files data
  221.         jecxz   .done
  222. ; seek to required item
  223.         mov     eax, [esp+8+4]
  224.         mov     esi, [ebx]
  225. .0:
  226.         test    esi, esi
  227.         jnz     .1
  228.         mov     esi, [ebx+8]
  229. .1:
  230.         add     esi, ebp
  231.         dec     eax
  232.         js      .2
  233.         mov     esi, [esi+file_common.next]
  234.         jmp     .0
  235. .2:
  236. .copy:
  237.         pushad
  238.         mov     eax, esi
  239.         mov     ecx, [ebp]
  240.         call    dword [getattrTable+(ecx-1)*4]
  241.         pop     edi esi
  242.         push    esi edi
  243.         add     edi, 40
  244.         mov     ecx, [esi+file_common.namelen]
  245.         mov     esi, [esi+file_common.name]
  246.         rep     movsb
  247.         mov     byte [edi], 0
  248.         popad
  249.         add     edi, 304
  250.         mov     esi, [esi+file_common.next]
  251.         test    esi, esi
  252.         jnz     @f
  253.         mov     esi, [ebx+8]
  254. @@:
  255.         add     esi, ebp
  256.         loop    .copy
  257. .done:
  258.         pop     eax
  259.         ret     10h
  260.  
  261. ; bool __stdcall SetFolder(HANDLE hPlugin,
  262. ;       const char* relative_path, const char* absolute_path);
  263. SetFolder:
  264.         mov     ebp, [esp+4]
  265.         mov     edx, [ebp+handle_common.curdir]
  266.         mov     esi, [esp+8]
  267.         cmp     dword [esi], '..'
  268.         jz      .toparent
  269.         xor     ecx, ecx
  270. @@:
  271.         inc     ecx
  272.         cmp     byte [esi+ecx], 0
  273.         jnz     @b
  274.         mov     ebx, [ebp+handle_common.root.subfolders]
  275.         test    edx, edx
  276.         jz      .scan
  277.         mov     ebx, [edx+file_common.subfolders]
  278. .scan:
  279.         test    ebx, ebx
  280.         jz      .err
  281.         add     ebx, ebp
  282.         cmp     [ebx+file_common.namelen], ecx
  283.         jnz     .cont
  284.         push    ecx esi
  285.         mov     edi, [ebx+file_common.name]
  286.         repz    cmpsb
  287.         pop     esi ecx
  288.         jz      .set
  289. .cont:
  290.         mov     ebx, [ebx+file_common.next]
  291.         jmp     .scan
  292. .toparent:
  293.         test    edx, edx
  294.         jz      .err
  295.         mov     ebx, [edx+file_common.parent]
  296.         test    ebx, ebx
  297.         jz      @f
  298.         add     ebx, ebp
  299. @@:
  300. .set:
  301.         mov     [ebp+handle_common.curdir], ebx
  302.         mov     al, 1
  303.         ret     12
  304. .err:
  305.         xor     eax, eax
  306.         ret     12
  307.  
  308. iglobal
  309. cur_stamp dd 0
  310. endg
  311.  
  312. uglobal
  313. tmp_bdfe        rb      304
  314. endg
  315.  
  316. ; void __stdcall GetFiles(HANDLE hPlugin, int NumItems, void* items[],
  317. ;       void* addfile, void* adddir);
  318. ;       bool __stdcall addfile(const char* name, void* bdfe_info, HANDLE hFile);
  319. ;       bool __stdcall adddir(const char* name, void* bdfe_info);
  320. GetFiles:
  321.         mov     ebp, [esp+4]
  322.         mov     ecx, [ebp+handle_common.NumFiles]
  323.         test    ecx, ecx
  324.         jz      .ret
  325.         mov     ebx, ebp
  326.         mov     eax, [ebx]
  327.         add     ebx, [basesizes+(eax-1)*8]
  328.         inc     [cur_stamp]
  329. .loop:
  330.         push    ecx
  331.         mov     esi, [ebx+file_common.fullname]
  332.         mov     edx, [ebp+handle_common.curdir]
  333.         test    edx, edx
  334.         jz      .incur
  335.         mov     eax, [cur_stamp]
  336.         mov     [edx+file_common.stamp], eax
  337.         mov     edi, [edx+file_common.fullname]
  338.         mov     ecx, [edx+file_common.namelen]
  339.         add     ecx, [edx+file_common.name]
  340.         sub     ecx, edi
  341.         repz    cmpsb
  342.         jnz     .cont
  343. .incur:
  344.         cmp     byte [esi], '/'
  345.         jnz     @f
  346.         inc     esi
  347. @@:
  348.         mov     ecx, [esp+12]   ; NumItems
  349.         mov     edx, [esp+16]   ; items
  350.         cmp     ecx, -1
  351.         jz      .ok
  352. .check:
  353.         sub     ecx, 1
  354.         js      .cont
  355.         push    esi
  356.         mov     edi, [edx]
  357.         add     edi, 40
  358. @@:
  359.         lodsb
  360.         scasb
  361.         jnz     @f
  362.         test    al, al
  363.         jz      .ok2
  364.         jmp     @b
  365. @@:
  366.         pop     esi
  367.         cmp     al, '/'
  368.         jnz     @f
  369.         cmp     byte [edi-1], 0
  370.         jz      .ok
  371. @@:
  372.         add     edx, 4
  373.         jmp     .check
  374. .ok2:
  375.         pop     esi
  376. .ok:
  377. ; add all parents directories if needed
  378. .parloope:
  379.         mov     ecx, [ebx+file_common.parent]
  380.         jecxz   .pardone
  381.         add     ecx, ebp
  382.         mov     eax, [cur_stamp]
  383.         cmp     [ecx+file_common.stamp], eax
  384.         jz      .pardone
  385. .parloopi:
  386.         mov     edx, ecx
  387.         mov     ecx, [ecx+file_common.parent]
  388.         jecxz   @f
  389.         add     ecx, ebp
  390.         cmp     [ecx+file_common.stamp], eax
  391.         jnz     .parloopi
  392. @@:
  393.         mov     [edx+file_common.stamp], eax
  394.         push    esi
  395.         mov     ecx, [edx+file_common.name]
  396.         add     ecx, [edx+file_common.namelen]
  397.         xor     eax, eax
  398.         xchg    al, [ecx]
  399.         push    eax ecx
  400.         mov     eax, edx
  401.         mov     edi, tmp_bdfe
  402.         push    edi
  403.         sub     esi, [ebx+file_common.fullname]
  404.         add     esi, [edx+file_common.fullname]
  405.         push    esi
  406.         mov     ecx, [ebp]
  407.         call    dword [getattrTable+(ecx-1)*4]
  408.         mov     eax, [esp+24+20]
  409.         call    eax
  410.         pop     ecx edx
  411.         mov     [ecx], dl
  412.         pop     esi
  413.         test    al, al
  414.         jz      .forced_exit
  415.         jmp     .parloope
  416. .pardone:
  417.         cmp     [ebx+file_common.bIsDirectory], 0
  418.         jz      .addfile
  419.         mov     eax, [cur_stamp]
  420.         cmp     [ebx+file_common.stamp], eax
  421.         jz      .cont
  422.         mov     [ebx+file_common.stamp], eax
  423.         push    esi
  424.         mov     ecx, [ebx+file_common.name]
  425.         add     ecx, [ebx+file_common.namelen]
  426.         xor     eax, eax
  427.         xchg    al, [ecx]
  428.         push    eax ecx
  429.         mov     eax, ebx
  430.         mov     edi, tmp_bdfe
  431.         push    edi
  432.         push    esi
  433.         mov     ecx, [ebp]
  434.         call    dword [getattrTable+(ecx-1)*4]
  435.         mov     eax, [esp+24+20]
  436.         call    eax
  437.         pop     ecx edx
  438.         mov     [ecx], dl
  439.         pop     esi
  440.         test    al, al
  441.         jz      .forced_exit
  442.         jmp     .cont
  443. .addfile:
  444.         push    ebx esi ebp
  445.         push    11h
  446.         pop     edi
  447.         mov     eax, ebx
  448.         mov     ecx, [ebp]
  449.         call    dword [openTable+(ecx-1)*4]
  450.         pop     ebp esi ebx
  451.         test    eax, eax
  452.         jz      .cont
  453.         push    eax
  454.         push    eax
  455.         mov     edi, tmp_bdfe
  456.         push    edi
  457.         push    esi
  458.         mov     eax, ebx
  459.         mov     ecx, [ebp]
  460.         call    dword [getattrTable+(ecx-1)*4]
  461.         mov     eax, [esp+20+16]
  462.         call    eax
  463.         pop     ecx
  464.         push    eax ebp
  465.         push    ebx
  466.         push    ecx
  467.         call    myclose
  468.         pop     ebx
  469.         pop     ebp eax
  470.         test    al, al
  471.         jz      .forced_exit
  472. .cont:
  473.         mov     eax, [ebp]
  474.         add     ebx, [basesizes+(eax-1)*8+4]
  475.         pop     ecx
  476.         dec     ecx
  477.         jnz     .loop
  478. .ret:
  479.         ret     20
  480. .forced_exit:
  481.         pop     ecx
  482.         jmp     .ret
  483.  
  484. ; void __stdcall GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo* info);
  485. GetOpenPluginInfo:
  486.         mov     eax, [esp+8]    ; get info ptr
  487.         mov     byte [eax], 3   ; flags: add non-existing '..' entry automatically
  488.                                 ;        use GetFiles for copying
  489.         ret     8
  490.  
  491. ; int __stdcall getattr(HANDLE hPlugin, const char* filename, void* info);
  492. mygetattr:
  493.         call    lookup_file_name
  494.         test    eax, eax
  495.         jz      @f
  496.         mov     edx, [ebp]
  497.         dec     edx
  498.         mov     edi, [esp+12]   ; info ptr
  499.         call    dword [getattrTable+edx*4]
  500.         xor     eax, eax
  501.         ret     12
  502. @@:
  503.         mov     al, 5   ; ERROR_FILE_NOT_FOUND
  504.         ret     12
  505.  
  506. ; HANDLE __stdcall open(HANDLE hPlugin, const char* filename, int mode);
  507. myopen:
  508.         call    lookup_file_name
  509.         test    eax, eax
  510.         jz      @f
  511.         mov     edx, [ebp]
  512.         dec     edx
  513.         mov     edi, [esp+12]   ; mode
  514.         call    dword [openTable+edx*4]
  515. @@:
  516.         ret     12
  517.  
  518. ; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
  519. myread:
  520.         mov     ebx, [esp+4]
  521.         mov     eax, [ebx]
  522.         jmp     dword [readTable+eax*4]
  523.  
  524. ; void __stdcall setpos(HANDLE hFile, __int64 pos);
  525. mysetpos:
  526.         mov     ebx, [esp+4]
  527.         mov     eax, [ebx]
  528.         jmp     dword [setposTable+eax*4]
  529.  
  530. ; void __stdcall close(HANDLE hFile);
  531. myclose:
  532.         mov     ebx, [esp+4]
  533.         mov     eax, [ebx]
  534.         jmp     dword [closeTable+eax*4]
  535.  
  536. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  537. ;;;;;;;;;;;;;; Auxiliary procedures ;;;;;;;;;;;;;
  538. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  539.  
  540. ; return.err and return.clear are labels to jmp if something is invalid
  541. ; the caller must previously define [_esp], [_ebp] and [error_proc], [clear_proc]
  542. return.err:
  543.         mov     esp, [_esp]
  544.         mov     ebp, [_ebp]
  545.         jmp     [error_proc]
  546. return.clear:
  547.         mov     esp, [_esp]
  548.         mov     ebp, [_ebp]
  549.         jmp     [clear_proc]
  550.  
  551. ; data for following routine
  552. iglobal
  553. align 4
  554. _24             dd      24
  555. _60             dd      60
  556. _10000000       dd      10000000
  557. days400year     dd      365*400+100-4+1
  558. days100year     dd      365*100+25-1
  559. days4year       dd      365*4+1
  560. days1year       dd      365
  561. months          dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  562. months2         dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  563. _400            dd      400
  564. _100            dd      100
  565. endg
  566.  
  567. ; Convert QWORD FILETIME to BDFE format.
  568. ntfs_datetime_to_bdfe:
  569. ; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
  570.         push    eax
  571.         mov     eax, edx
  572.         xor     edx, edx
  573.         div     [_10000000]
  574.         xchg    eax, [esp]
  575.         div     [_10000000]
  576.         pop     edx
  577. ; edx:eax = number of seconds since January 1, 1601
  578.         push    eax
  579.         mov     eax, edx
  580.         xor     edx, edx
  581.         div     [_60]
  582.         xchg    eax, [esp]
  583.         div     [_60]
  584.         mov     [edi], dl
  585.         pop     edx
  586. ; edx:eax = number of minutes
  587.         div     [_60]
  588.         mov     [edi+1], dl
  589. ; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
  590.         xor     edx, edx
  591.         div     [_24]
  592.         mov     [edi+2], dl
  593.         mov     [edi+3], byte 0
  594. ; eax = number of days since January 1, 1601
  595.         xor     edx, edx
  596.         div     [days400year]
  597.         imul    eax, 400
  598.         add     eax, 1601
  599.         mov     [edi+6], ax
  600.         mov     eax, edx
  601.         xor     edx, edx
  602.         div     [days100year]
  603.         cmp     al, 4
  604.         jnz     @f
  605.         dec     eax
  606.         add     edx, [days100year]
  607. @@:
  608.         imul    eax, 100
  609.         add     [edi+6], ax
  610.         mov     eax, edx
  611.         xor     edx, edx
  612.         div     [days4year]
  613.         shl     eax, 2
  614.         add     [edi+6], ax
  615.         mov     eax, edx
  616.         xor     edx, edx
  617.         div     [days1year]
  618.         cmp     al, 4
  619.         jnz     @f
  620.         dec     eax
  621.         add     edx, [days1year]
  622. @@:
  623.         add     [edi+6], ax
  624.         push    esi edx
  625.         mov     esi, months
  626.         movzx   eax, word [edi+6]
  627.         test    al, 3
  628.         jnz     .noleap
  629.         xor     edx, edx
  630.         push    eax
  631.         div     [_400]
  632.         pop     eax
  633.         test    edx, edx
  634.         jz      .leap
  635.         xor     edx, edx
  636.         div     [_100]
  637.         test    edx, edx
  638.         jz      .noleap
  639. .leap:
  640.         mov     esi, months2
  641. .noleap:
  642.         pop     edx
  643.         xor     eax, eax
  644.         inc     eax
  645. @@:
  646.         sub     edx, [esi]
  647.         jb      @f
  648.         add     esi, 4
  649.         inc     eax
  650.         jmp     @b
  651. @@:
  652.         add     edx, [esi]
  653.         pop     esi
  654.         inc     edx
  655.         mov     [edi+4], dl
  656.         mov     [edi+5], al
  657.         add     edi, 8
  658.         ret
  659.  
  660. ; By given array of files information, initialize links between them
  661. ; ("[folder] contains [item]" relations).
  662. ; Information structure must be compatible with 'file_common'.
  663. ; Size of information structure is in [esp+4].
  664. init_file_links:
  665. ; in: edx->file infos, ebx = number of files, [esp+4] = size,
  666. ;     edi->{dd root.subfolders, dd root.subfolders.end,
  667. ;           dd root.subfiles, dd root.subfiles.end, dd root.NumItems}
  668.         xor     eax, eax
  669.         mov     [.free], eax
  670.         push    edi
  671.         stosd
  672.         stosd
  673.         stosd
  674.         stosd
  675.         stosd
  676.         pop     edi
  677. ; Loop through all files
  678. .mainloop:
  679.         dec     ebx
  680.         js      .mainloopdone
  681. ; Parse file name
  682. ; esi->current character in name
  683. ; dword [esp] = start of current component in file name
  684. ; ecx->{dd curdir.subfolders, dd curdir.subfolders.end,
  685. ;       dd curdir.subfiles, dd curdir.subfiles.end}
  686.         mov     esi, [edx+file_common.fullname]
  687.         mov     ecx, edi
  688. .parseloop:
  689.         push    esi
  690. .parsename:
  691.         lodsb
  692.         test    al, al
  693.         jz      @f
  694.         cmp     al, '/'
  695.         jnz     .parsename
  696. @@:
  697. ; we have found next component of current name; look for it in current directory
  698.         sub     esi, [esp]
  699.         dec     esi     ; esi = strlen(component)
  700.         cmp     esi, 259
  701.         jbe     @f
  702.         push    ContinueBtn
  703.         push    1
  704.         push    aNameTooLong_ptr
  705.         push    1
  706.         call    [SayErr]
  707.         jmp     return.clear
  708. @@:
  709.         push    ecx
  710.         mov     eax, [ecx]      ; eax->subfolders list
  711.         mov     ecx, esi
  712. .scansubfolders:
  713.         test    eax, eax
  714.         jz      .nofolder
  715.         add     eax, [hOut]
  716.         cmp     [eax+file_common.namelen], ecx
  717.         jnz     .scancont
  718.         mov     esi, [esp+4]
  719.         push    ecx edi
  720.         mov     edi, [eax+file_common.name]
  721.         repz    cmpsb
  722.         pop     edi ecx
  723.         jz      .subfound
  724. .scancont:
  725.         mov     eax, [eax+file_common.next]
  726.         jmp     .scansubfolders
  727. .subfound:
  728. ; found subfolder, set it as current and continue parsing name
  729.         add     [esp+4], ecx
  730.         pop     ecx
  731.         lea     ecx, [eax+file_common.subfolders]
  732.         pop     esi
  733.         lodsb
  734.         test    al, al
  735.         jnz     .parseloop
  736. ; that was the last component of the name, and we have found subfolder
  737. ; so found subfolder is a virtual subfolder and must be replaced with current
  738. ; name
  739.         mov     eax, [ecx-file_common.subfolders+file_common.namelen]
  740.         mov     [edx+file_common.namelen], eax
  741.         sub     esi, eax
  742.         dec     esi
  743.         mov     [edx+file_common.name], esi
  744.         sub     edx, [hOut]     ; convert pointer to relative
  745. ; replace item in L2-list
  746.         mov     eax, [ecx-file_common.subfolders+file_common.prev]
  747.         test    eax, eax
  748.         jnz     .1
  749.         mov     eax, [ecx-file_common.subfolders+file_common.parent]
  750.         sub     eax, file_common.next - file_common.subfolders
  751.         jnc     .1
  752.         lea     eax, [edi-file_common.next]
  753.         jmp     .2
  754. .1:
  755.         add     eax, [hOut]
  756. .2:
  757.         mov     [eax+file_common.next], edx
  758.         mov     eax, [ecx-file_common.subfolders+file_common.next]
  759.         test    eax, eax
  760.         jnz     .3
  761.         mov     eax, [ecx-file_common.subfolders+file_common.parent]
  762.         sub     eax, file_common.prev - file_common.subfolders.end
  763.         jnc     .3
  764.         lea     eax, [edi-file_common.prev+4]
  765.         jmp     .4
  766. .3:
  767.         add     eax, [hOut]
  768. .4:
  769.         mov     [eax+file_common.prev], edx
  770. ; correct parent links in childrens
  771.         mov     eax, [ecx]
  772. @@:
  773.         test    eax, eax
  774.         jz      @f
  775.         add     eax, [hOut]
  776.         mov     [eax+file_common.parent], edx
  777.         mov     eax, [eax+file_common.next]
  778.         jmp     @b
  779. @@:
  780.         mov     eax, [ecx+8]
  781. @@:
  782.         test    eax, eax
  783.         jz      @f
  784.         add     eax, [hOut]
  785.         mov     [eax+file_common.parent], edx
  786.         mov     eax, [eax+file_common.next]
  787.         jmp     @b
  788. @@:
  789.         add     edx, [hOut]
  790. ; set children links
  791.         mov     eax, [ecx]
  792.         mov     [edx+file_common.subfolders], eax
  793.         mov     eax, [ecx+4]
  794.         mov     [edx+file_common.subfolders.end], eax
  795.         mov     eax, [ecx+8]
  796.         mov     [edx+file_common.subfiles], eax
  797.         mov     eax, [ecx+12]
  798.         mov     [edx+file_common.subfiles.end], eax
  799.         mov     eax, [ecx+16]
  800.         mov     [edx+file_common.NumSubItems], eax
  801. ; set prev/next links
  802.         mov     eax, [ecx-file_common.subfolders+file_common.next]
  803.         mov     [edx+file_common.next], eax
  804.         mov     eax, [ecx-file_common.subfolders+file_common.prev]
  805.         mov     [edx+file_common.prev], eax
  806. ; add old item to list of free items
  807. uglobal
  808. align 4
  809. init_file_links.free    dd      ?
  810. endg
  811.         sub     ecx, file_common.subfolders
  812.         mov     eax, [.free]
  813.         mov     [ecx], eax
  814.         sub     ecx, [hOut]
  815.         mov     [.free], ecx
  816.         jmp     .mainloopcont
  817. .nofolder:
  818.         mov     eax, edx
  819.         mov     esi, [esp+4]
  820.         cmp     byte [esi+ecx], 0
  821.         jz      .newitem
  822. ; the current item is as 'dir1/item1' and 'dir1' has not been found
  823. ; allocate virtual subfolder 'dir1'
  824.         mov     eax, [init_file_links.free]
  825.         test    eax, eax
  826.         jz      .realloc
  827.         add     eax, [hOut]
  828.         push    dword [eax]
  829.         pop     [init_file_links.free]
  830.         jmp     .allocated
  831. .realloc:
  832. ; there is no free space, so reallocate [hOut] block
  833.         mov     eax, [hOut]
  834.         sub     [esp], eax      ; make pointers relative
  835.         sub     edx, eax
  836.         sub     edi, eax
  837.         push    ecx
  838.         mov     ecx, [hOut.allocated]
  839.         add     ecx, [esp+12+4]
  840.         mov     [hOut.allocated], ecx
  841.         push    ecx
  842.         and     ecx, 0xFFF
  843.         cmp     ecx, [esp+16+4]
  844.         pop     ecx
  845.         ja      @f
  846.         push    edx
  847.         mov     edx, eax
  848.         call    [pgrealloc]
  849.         pop     edx
  850.         test    eax, eax
  851.         jnz     @f
  852.         mov     ecx, [hOut]
  853.         call    [pgfree]
  854.         mov     esp, [_esp]
  855.         or      eax, -1
  856.         ret
  857. @@:
  858.         pop     ecx
  859.         mov     [hOut], eax
  860.         add     [esp], eax      ; make pointers absolute
  861.         add     edx, eax
  862.         add     edi, eax
  863.         add     eax, [hOut.allocated]
  864.         sub     eax, [esp+8+4]
  865. .allocated:
  866. ; eax -> new item
  867.         mov     [eax+file_common.bIsDirectory], 1
  868.         mov     [eax+file_common.bPseudoFolder], 1
  869. .newitem:
  870.         mov     [eax+file_common.namelen], ecx
  871. ; !!! in this case .fullname is not null-terminated !!!
  872.         mov     ecx, [edx+file_common.fullname]
  873.         mov     [eax+file_common.fullname], ecx
  874.         push    edi eax
  875.         lea     edi, [eax+file_common.parent]
  876.         xor     eax, eax
  877.         push    7
  878.         pop     ecx
  879.         rep     stosd
  880.         pop     eax edi
  881.         pop     ecx
  882.         pop     esi
  883. ; ecx = parent item, eax = current item
  884.         mov     [eax+file_common.name], esi
  885.         inc     dword [ecx+16]  ; new item in parent folder
  886.         push    ecx
  887. ; add new item to end of L2-list
  888.         cmp     [eax+file_common.bIsDirectory], 0
  889.         jnz     @f
  890.         add     ecx, 8
  891. @@:
  892.         push    eax
  893.         sub     eax, [hOut]
  894.         cmp     dword [ecx], 0
  895.         jnz     @f
  896.         mov     [ecx], eax
  897. @@:
  898.         xchg    eax, [ecx+4]
  899.         xchg    eax, ecx
  900.         pop     eax
  901.         mov     [eax+file_common.prev], ecx
  902.         jecxz   @f
  903.         add     ecx, [hOut]
  904.         sub     eax, [hOut]
  905.         mov     [ecx+file_common.next], eax
  906.         add     eax, [hOut]
  907. @@:
  908.         pop     ecx
  909. ; set parent link
  910.         cmp     ecx, edi
  911.         jz      @f
  912.         sub     ecx, file_common.subfolders
  913.         sub     ecx, [hOut]
  914.         mov     [eax+file_common.parent], ecx
  915. @@:
  916. ; set current directory to current item
  917.         lea     ecx, [eax+file_common.subfolders]
  918. ; if that was not last component, continue parse name
  919.         add     esi, [eax+file_common.namelen]
  920.         lodsb
  921.         test    al, al
  922.         jnz     .parseloop
  923. .mainloopcont:
  924. ; continue main loop
  925.         add     edx, [esp+4]
  926.         jmp     .mainloop
  927. .mainloopdone:
  928. ; Loop done.
  929.         ret     4
  930.  
  931. ; This subroutine is called by getattr and open.
  932. ; This subroutine looks for file name and returns NULL or pointer to file info record.
  933. lookup_file_name:
  934.         mov     ebp, [esp+8]    ; hPlugin
  935.         mov     esi, [esp+12]   ; filename
  936.         lea     edi, [ebp+handle_common.root.subfolders]
  937.         xor     eax, eax
  938. ; KFar operates with absolute names, skip first '/'
  939.         cmp     byte [esi], '/'
  940.         jnz     .notfound
  941.         inc     esi
  942. .mainloop:
  943. ; get next component of name
  944.         push    -1
  945.         pop     ecx
  946. @@:
  947.         inc     ecx
  948.         cmp     byte [esi+ecx], '/'
  949.         jz      @f
  950.         cmp     byte [esi+ecx], 0
  951.         jnz     @b
  952. @@:
  953. ; esi->component, ecx=length
  954. ; scan for required item in subfolders list
  955.         push    -1
  956.         mov     eax, [edi]      ; .subfolders
  957. .scan1:
  958.         test    eax, eax
  959.         jz      .notfound1
  960.         add     eax, ebp
  961.         cmp     [eax+file_common.namelen], ecx
  962.         jnz     .cont1
  963.         push    ecx esi edi
  964.         mov     edi, [eax+file_common.name]
  965.         repz    cmpsb
  966.         pop     edi esi ecx
  967.         jz      .found1
  968. .cont1:
  969.         mov     eax, [eax+file_common.next]
  970.         jmp     .scan1
  971. .notfound1:
  972.         pop     edx
  973. ; if this is last component in file name, scan in subfiles list
  974.         cmp     byte [esi+ecx], al
  975.         jnz     .notfound
  976.         inc     edx
  977.         jnz     .notfound
  978.         mov     eax, [edi+8]    ; .subfiles
  979.         push    edx
  980.         jmp     .scan1
  981. .found1:
  982.         pop     edi
  983. ; item is found, go to next component
  984.         lea     edi, [eax+file_common.subfolders]
  985.         lea     esi, [esi+ecx+1]
  986.         cmp     byte [esi-1], 0
  987.         jnz     .mainloop
  988. ; this was the last component
  989. .notfound:
  990.         ret
  991.  
  992. ; Memory streams handling.
  993. ; Archive handlers create memory stream for small files:
  994. ; size of which is not greater than (free RAM size)/4 and
  995. ; not greater than following constant...
  996. ;LIMIT_FOR_MEM_STREAM = 2*1024*1024
  997. ; ...if it is defined. Now the definition is commented:
  998. ; if user has many physical memory, why not to use it?
  999.  
  1000. virtual at 0
  1001. mem_stream:
  1002. .type   dd      ?       ; type_mem_stream
  1003. .size   dd      ?
  1004. .pos    dd      ?
  1005. .buf:
  1006. end virtual
  1007.  
  1008. ; unsigned __stdcall read(ebx = HANDLE hFile, void* buf, unsigned size);
  1009. read_mem_stream:
  1010.         mov     eax, [esp+12]
  1011.         mov     ecx, [ebx+mem_stream.size]
  1012.         sub     ecx, [ebx+mem_stream.pos]
  1013.         jnc     @f
  1014.         xor     ecx, ecx
  1015. @@:
  1016.         cmp     eax, ecx
  1017.         jb      @f
  1018.         mov     eax, ecx
  1019. @@:
  1020.         mov     ecx, eax
  1021.         lea     esi, [ebx+mem_stream.buf]
  1022.         add     esi, [ebx+mem_stream.pos]
  1023.         add     [ebx+mem_stream.pos], eax
  1024.         mov     edi, [esp+8]
  1025.         mov     edx, ecx
  1026.         shr     ecx, 2
  1027.         rep     movsd
  1028.         mov     ecx, edx
  1029.         and     ecx, 3
  1030.         rep     movsb
  1031.         ret     12
  1032.  
  1033. ; void __stdcall setpos(ebx = HANDLE hFile, __int64 pos);
  1034. setpos_mem_stream:
  1035.         mov     eax, [esp+8]
  1036.         mov     [ebx+mem_stream.pos], eax
  1037.         ret     12
  1038.  
  1039. ; void __stdcall close(ebx = HANDLE hFile);
  1040. close_mem_stream:
  1041.         mov     ecx, ebx
  1042.         call    [pgfree]
  1043.         ret     4
  1044.  
  1045. ; Allocate handle for file
  1046. ; esi -> handle table, ecx = size of handle
  1047. alloc_handle:
  1048. ; Handle table is L2-list of allocated pages.
  1049. ; Scan for free entry
  1050.         mov     edx, esi
  1051. @@:
  1052.         mov     edx, [edx]
  1053.         cmp     edx, esi
  1054.         jz      .alloc_new
  1055.         mov     eax, [edx+8]            ; head of L1-list of free entries
  1056.         test    eax, eax                ; has free entry?
  1057.         jz      @b
  1058. ; we have found allocated page with free entry; allocate entry and return
  1059.         inc     dword [edx+12]          ; number of busy entries
  1060.         push    dword [eax]
  1061.         pop     dword [edx+8]
  1062. .ret:
  1063.         ret
  1064. .alloc_new:
  1065. ; no free pages; get new page and initialize
  1066.         push    ecx
  1067.         mov     ecx, 0x1000
  1068.         call    [pgalloc]
  1069.         pop     ecx
  1070.         test    eax, eax
  1071.         jz      .ret
  1072. ; insert new page to start of L2-list
  1073.         mov     edx, [esi]
  1074.         mov     [eax], edx
  1075.         mov     [esi], eax
  1076.         mov     [eax+4], esi
  1077.         mov     [edx+4], eax
  1078.         mov     dword [eax+12], 1       ; 1 allocated entry
  1079. ; initialize list of free entries
  1080.         lea     edx, [eax+16]
  1081.         push    edx     ; save return value
  1082.         add     edx, ecx
  1083.         mov     [eax+8], edx
  1084.         add     eax, 0x1000
  1085. @@:
  1086.         mov     esi, edx
  1087.         add     edx, ecx
  1088.         mov     [esi], edx
  1089.         cmp     edx, eax
  1090.         jb      @b
  1091.         and     dword [esi], 0
  1092.         pop     eax
  1093.         ret
  1094.  
  1095. ; Free handle allocated in previous procedure
  1096. ; esi = handle
  1097. free_handle:
  1098.         mov     ecx, esi
  1099.         and     ecx, not 0xFFF  ; get page
  1100. ; add entry to head of L1-list of free entries
  1101.         mov     eax, [ecx+8]
  1102.         mov     [esi], eax
  1103.         mov     [ecx+8], esi
  1104.         dec     dword [ecx+12]  ; decrement number of allocated entries
  1105.         jnz     .ret
  1106. ; delete page from common L2-list
  1107.         mov     eax, [ecx]
  1108.         mov     edx, [ecx+4]
  1109.         mov     [eax+4], edx
  1110.         mov     [edx], eax
  1111. ; free page
  1112.         call    [pgfree]
  1113. .ret:
  1114.         ret
  1115.  
  1116. ; Ask user to enter password.
  1117. ; Out: ZF set <=> user pressed Esc
  1118. ;      'password_ansi', 'password_unicode', 'password_size' filled
  1119. query_password:
  1120.         cmp     [bPasswordDefined], 0
  1121.         jnz     .ret
  1122.         mov     edi, password_data
  1123.         mov     eax, password_maxlen
  1124.         stosd           ; maximum length
  1125.         xor     eax, eax
  1126.         stosd           ; start of visible part
  1127.         stosd           ; position of cursor
  1128.         stosb           ; initial state: empty string
  1129.         mov     eax, [cur_console_size]
  1130.         mov     eax, [eax]      ; get current console width
  1131.         sub     eax, 12
  1132.         mov     edi, password_dlg
  1133.         mov     [edi+password_dlg.width-password_dlg], eax
  1134.         dec     eax
  1135.         dec     eax
  1136.         mov     [edi+password_dlg.width1-password_dlg], eax
  1137.         mov     [edi+password_dlg.width2-password_dlg], eax
  1138.         push    edi
  1139.         call    [DialogBox]
  1140.         inc     eax
  1141.         jz      .ret
  1142. ; convert ANSI-cp866 to UNICODE string; also calculate 'password_size'
  1143.         mov     esi, password_ansi
  1144.         mov     edi, password_unicode
  1145.         or      [password_size], -1
  1146. .cvt:
  1147.         inc     [password_size]
  1148.         lodsb
  1149.         mov     ah, 0
  1150. ; 0x00-0x7F - trivial map
  1151.         cmp     al, 0x80
  1152.         jb      .symb
  1153. ; 0x80-0xAF -> 0x410-0x43F
  1154.         cmp     al, 0xB0
  1155.         jae     @f
  1156.         add     ax, 0x410-0x80
  1157.         jmp     .symb
  1158. @@:
  1159. ; 0xE0-0xEF -> 0x440-0x44F
  1160.         cmp     al, 0xE0
  1161.         jb      .unk
  1162.         cmp     al, 0xF0
  1163.         jae     @f
  1164.         add     ax, 0x440-0xE0
  1165.         jmp     .symb
  1166. @@:
  1167. ; 0xF0 -> 0x401
  1168. ; 0xF1 -> 0x451
  1169.         cmp     al, 'Ё'
  1170.         jz      .yo1
  1171.         cmp     al, 'ё'
  1172.         jz      .yo2
  1173. .unk:
  1174.         mov     al, '_'
  1175.         jmp     .symb
  1176. .yo1:
  1177.         mov     ax, 0x401
  1178.         jmp     .symb
  1179. .yo2:
  1180.         mov     ax, 0x451
  1181. .symb:
  1182.         stosw
  1183.         test    al, al
  1184.         jnz     .cvt
  1185.         inc     [bPasswordDefined]      ; clears ZF flag
  1186. .ret:
  1187.         ret
  1188.  
  1189. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1190. ;;;;;;;;;;;;; API for other programs ;;;;;;;;;;;;
  1191. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1192. ; void* __stdcall deflate_unpack(void* packed_data, unsigned* pLength)
  1193. deflate_unpack:
  1194.         push    dword [esp+8]
  1195.         push    esp
  1196.         push    deflate_unpack_cb
  1197.         call    deflate_unpack2
  1198.         ret     8
  1199.  
  1200. deflate_unpack_cb:
  1201.         mov     edx, [esp+4]
  1202.         push    edx
  1203.         mov     edx, [edx+12]
  1204.         mov     edx, [edx]
  1205.         mov     eax, [esp+8+4]
  1206.         mov     [eax], edx
  1207.         pop     edx
  1208.         xor     eax, eax
  1209.         xchg    eax, [edx+8]
  1210.         ret     8
  1211.  
  1212. ; void* __stdcall deflate_unpack2(void* get_next_chunk, void* parameter, unsigned* pUnpackedLength)
  1213. ;       void* __stdcall get_next_chunk(void* parameter, unsigned* pLength)
  1214. deflate_unpack2:
  1215.         pusha
  1216.         mov     ecx, 0x11000
  1217.         call    mypgalloc
  1218.         test    eax, eax
  1219.         jz      .ret
  1220.         or      dword [eax+streamInfo.fullSize], -1
  1221.         or      dword [eax+streamInfo.fullSize+4], -1
  1222.         and     dword [eax+streamInfo.bufSize], 0
  1223.         mov     dword [eax+streamInfo.fillBuf], .fillBuf
  1224.         mov     edx, [esp+32+4]
  1225.         mov     [eax+streamInfo.size], edx
  1226.         mov     edx, [esp+32+8]
  1227.         mov     [eax+streamInfo.size+4], edx
  1228.         mov     [eax+streamInfo.size+8+deflate_decoder.inStream], eax
  1229.         add     eax, streamInfo.size+8
  1230.         lea     edi, [eax+deflate_decoder.size]
  1231.         mov     [eax+streamInfo.bufPtr], edi
  1232.         mov     ebp, eax
  1233.         call    deflate_init_decoder
  1234.         xor     edx, edx
  1235.         mov     ecx, 10000h
  1236. .loop:
  1237.         push    @f
  1238.         pushad
  1239.         mov     [_esp], esp
  1240.         mov     [_ebp], ebp
  1241.         mov     [error_proc], .error
  1242.         mov     ecx, 10000h
  1243.         jmp     [eax+streamInfo.fillBuf]
  1244. @@:
  1245.         push    68
  1246.         pop     eax
  1247.         push    20
  1248.         pop     ebx
  1249.         int     0x40
  1250.         test    eax, eax
  1251.         jz      .nomem
  1252.         mov     edx, eax
  1253.         mov     eax, ebp
  1254.         mov     esi, edi
  1255.         push    edi
  1256.         lea     edi, [edx+ecx-0x10000]
  1257.         push    ecx
  1258.         mov     ecx, 0x10000/4
  1259.         rep     movsd
  1260.         pop     ecx
  1261.         pop     edi
  1262.         add     ecx, 0x10000
  1263.         jmp     .loop
  1264. .error:
  1265.         pop     eax
  1266.         push    edi
  1267.         popad
  1268.         pop     eax
  1269.         mov     eax, ebp
  1270.         lea     esi, [eax+deflate_decoder.size]
  1271.         sub     ecx, 0x10000
  1272.         sub     edi, esi
  1273.         add     ecx, edi
  1274.         mov     eax, [esp+32+12]
  1275.         test    eax, eax
  1276.         jz      @f
  1277.         mov     [eax], ecx
  1278. @@:
  1279.         test    ecx, ecx
  1280.         jnz     @f
  1281.         inc     ecx
  1282. @@:
  1283.         push    68
  1284.         pop     eax
  1285.         push    20
  1286.         pop     ebx
  1287.         int     0x40
  1288.         test    eax, eax
  1289.         jz      .nomem
  1290.         sub     ecx, edi
  1291.         mov     edx, edi
  1292.         lea     edi, [eax+ecx]
  1293.         mov     ecx, edx
  1294.         shr     ecx, 2
  1295.         rep     movsd
  1296.         mov     ecx, edx
  1297.         and     ecx, 3
  1298.         rep     movsb
  1299.         push    eax
  1300.         push    68
  1301.         pop     eax
  1302.         push    13
  1303.         pop     ebx
  1304.         lea     ecx, [ebp-streamInfo.size-8]
  1305.         int     40h
  1306.         pop     eax
  1307.         jmp     .ret
  1308. .nomem:
  1309.         push    68
  1310.         pop     eax
  1311.         push    13
  1312.         pop     ebx
  1313.         test    edx, edx
  1314.         jz      @f
  1315.         mov     ecx, edx
  1316.         push    eax
  1317.         int     0x40
  1318.         pop     eax
  1319. @@:
  1320.         lea     ecx, [ebp-streamInfo.size-8]
  1321.         int     0x40
  1322.         xor     eax, eax
  1323. .ret:
  1324.         mov     [esp+28], eax
  1325.         popa
  1326.         ret     12
  1327. .fillBuf:
  1328.         push    eax
  1329.         push    eax
  1330.         push    esp
  1331.         push    dword [eax+streamInfo.size+4]
  1332.         call    dword [eax+streamInfo.size]
  1333.         pop     edx
  1334.         pop     ebp
  1335.         mov     [ebp+streamInfo.bufPtr], eax
  1336.         and     [ebp+streamInfo.bufDataLen], 0
  1337.         test    eax, eax
  1338.         jz      @f
  1339.         mov     [ebp+streamInfo.bufDataLen], edx
  1340. @@:
  1341.         popad
  1342.         ret
  1343.  
  1344. mypgalloc:
  1345.         push    68
  1346.         pop     eax
  1347.         push    12
  1348.         pop     ebx
  1349.         int     0x40
  1350.         ret
  1351.  
  1352. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1353. ;;;;;;;;;;;;;;;; Initialized data ;;;;;;;;;;;;;;;
  1354. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1355.  
  1356. ; export table
  1357. align 4
  1358. EXPORTS:
  1359.         dd      aVersion,       3
  1360.         dd      aPluginLoad,    plugin_load
  1361.         dd      aOpenFilePlugin,OpenFilePlugin
  1362.         dd      aClosePlugin,   ClosePlugin
  1363.         dd      aReadFolder,    ReadFolder
  1364.         dd      aSetFolder,     SetFolder
  1365.         dd      aGetFiles,      GetFiles
  1366.         dd      aGetOpenPluginInfo, GetOpenPluginInfo
  1367.         dd      aGetattr,       mygetattr
  1368.         dd      aOpen,          myopen
  1369.         dd      aRead,          myread
  1370.         dd      aSetpos,        mysetpos
  1371.         dd      aClose,         myclose
  1372.         dd      aDeflateUnpack, deflate_unpack
  1373.         dd      aDeflateUnpack2,deflate_unpack2
  1374.         dd      0
  1375.  
  1376. ; exported names
  1377. aVersion        db      'version',0
  1378. aPluginLoad     db      'plugin_load',0
  1379. aOpenFilePlugin db      'OpenFilePlugin',0
  1380. aClosePlugin    db      'ClosePlugin',0
  1381. aReadFolder     db      'ReadFolder',0
  1382. aSetFolder      db      'SetFolder',0
  1383. aGetFiles       db      'GetFiles',0
  1384. aGetOpenPluginInfo db   'GetOpenPluginInfo',0
  1385. aGetattr        db      'getattr',0
  1386. aOpen           db      'open',0
  1387. aRead           db      'read',0
  1388. aSetpos         db      'setpos',0
  1389. aClose          db      'close',0
  1390. aDeflateUnpack  db      'deflate_unpack',0
  1391. aDeflateUnpack2 db      'deflate_unpack2',0
  1392.  
  1393. ; common strings
  1394. if lang eq ru
  1395. aContinue       db      'Продолжить',0
  1396. aCancel         db      'Отмена',0
  1397. aHeaderError    db      'Ошибка в заголовке архива',0
  1398. aReadError      db      'Ошибка чтения',0
  1399. aNoFreeRam      db      'Недостаточно свободной оперативной памяти',0
  1400. aEncodingProblem db     'Проблема с кодировкой',0
  1401. aEncodingProblem_str db 'Имена некоторых файлов в архиве содержат символы,',0
  1402. .2              db      'не представимые в кодировке cp866.',0
  1403. .3              db      'Эти символы будут заменены на подчёркивания.',0
  1404. aEnterPassword  db      'Введите пароль:',0
  1405. aEnterPasswordLen = $ - aEnterPassword - 1
  1406. aEnterPasswordTitle db  'Ввод пароля',0
  1407. aArchiveDataError db    'Ошибка в данных архива',0
  1408. aArchiveDataErrorPass db 'Ошибка в данных архива или неверный пароль',0
  1409. aChangePass     db      'Ввести пароль',0
  1410. aNameTooLong    db      'Слишком длинное имя',0
  1411. aCannotOpenFile db      'Не могу открыть файл',0
  1412. else
  1413. aContinue       db      'Continue',0
  1414. aCancel         db      'Cancel',0
  1415. aHeaderError    db      'Invalid archive header',0
  1416. aReadError      db      'Read error',0
  1417. aNoFreeRam      db      'There is not enough of free RAM',0
  1418. aEncodingProblem db     'Encoding problem',0
  1419. aEncodingProblem_str db 'The names of some files in the archive contain',0
  1420. .2              db      'characters which can not be represented in cp866.',0
  1421. .3              db      'Such characters will be replaced to underscores.',0
  1422. aEnterPassword  db      'Enter password:',0
  1423. aEnterPasswordLen = $ - aEnterPassword - 1
  1424. aEnterPasswordTitle db  'Get password',0
  1425. aArchiveDataError db    'Error in archive data',0
  1426. aArchiveDataErrorPass db 'Error in archive data or incorrect password',0
  1427. aChangePass     db      'Enter password',0
  1428. aNameTooLong    db      'Name is too long',0
  1429. aCannotOpenFile db      'Cannot open file',0
  1430. end if
  1431.  
  1432. ; kfar_arc supports many archive types.
  1433. ; OpenFilePlugin looks for supported archive signature and gives control
  1434. ;   to concrete handler if found.
  1435. ; Other functions just determine type of opened archive and jump to corresponding handler.
  1436. type_mem_stream = 0     ; memory stream - for file handles (returned from 'open')
  1437. type_7z = 1
  1438. type_zip = 2
  1439.  
  1440. ; archive functions (types start from type_7z)
  1441. align 4
  1442. ClosePluginTable:
  1443.         dd      close_7z
  1444.         dd      close_zip
  1445. getattrTable:
  1446.         dd      getattr_7z
  1447.         dd      getattr_zip
  1448. openTable:
  1449.         dd      open_file_7z
  1450.         dd      open_file_zip
  1451. basesizes:
  1452.         dd      handle_7z.basesize, file_in_7z.size
  1453.         dd      handle_zip.basesize, file_in_zip.size
  1454.  
  1455. ; file functions (types start from type_mem_stream)
  1456. readTable:
  1457.         dd      read_mem_stream
  1458.         dd      read_7z
  1459.         dd      read_zip
  1460. setposTable:
  1461.         dd      setpos_mem_stream
  1462.         dd      setpos_7z
  1463.         dd      setpos_zip
  1464. closeTable:
  1465.         dd      close_mem_stream
  1466.         dd      close_file_7z
  1467.         dd      close_file_zip
  1468.  
  1469. ; pointers for SayErr and Message
  1470. ContinueBtn     dd      aContinue
  1471. HeaderError_ptr dd      aHeaderError
  1472. aReadError_ptr  dd      aReadError
  1473. aNoFreeRam_ptr  dd      aNoFreeRam
  1474. aEncodingProblem_str_ptr:
  1475.                 dd      aEncodingProblem_str
  1476.                 dd      aEncodingProblem_str.2
  1477.                 dd      aEncodingProblem_str.3
  1478. aNameTooLong_ptr dd     aNameTooLong
  1479. aArchiveDataError_ptr dd aArchiveDataError
  1480. aArchiveDataErrorPass_ptr dd aArchiveDataErrorPass
  1481. CancelPassBtn   dd      aCancel
  1482.                 dd      aChangePass
  1483.  
  1484. ; "enter password" dialog for KFar
  1485. password_dlg:
  1486.         dd      1       ; use standard dialog colors
  1487.         dd      -1      ; center window by x
  1488.         dd      -1      ; center window by y
  1489. .width  dd      ?       ; width (will be filled according to current console width)
  1490.         dd      2       ; height
  1491.         dd      4, 2    ; border size
  1492.         dd      aEnterPasswordTitle     ; title
  1493.         dd      ?       ; colors (will be set by KFar)
  1494.         dd      0       ; used internally by dialog manager, ignored
  1495.         dd      0, 0    ; reserved for DlgProc
  1496.         dd      2       ; 2 controls
  1497. ; the string "enter password"
  1498.         dd      1       ; type: static
  1499.         dd      1,0     ; upper-left position
  1500. .width1 dd      ?,0     ; bottom-right position
  1501.         dd      aEnterPassword  ; data
  1502.         dd      0       ; flags
  1503. ; editbox for password
  1504.         dd      3       ; type: edit
  1505.         dd      1,1     ; upper-left position
  1506. .width2 dd      ?,0     ; bottom-right position
  1507.         dd      password_data   ; data
  1508.         dd      2Ch     ; flags
  1509.  
  1510. IncludeIGlobals
  1511.  
  1512. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1513. ;;;;;;;;;;;;;;; Uninitialized data ;;;;;;;;;;;;;;
  1514. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1515.  
  1516. section '.udata' data readable writable align 16
  1517. kfar_info       dd      ?
  1518. crc_table       rd      256
  1519. _esp            dd      ?
  1520. _ebp            dd      ?
  1521. bufsize         dd      ?
  1522. bufptr          dd      ?
  1523. bufend          dd      ?
  1524. buffer          rb      1024
  1525. inStream        dd      ?
  1526. hOut            dd      ?
  1527. .allocated      dd      ?
  1528.  
  1529. error_proc      dd      ?
  1530. clear_proc      dd      ?
  1531.  
  1532. ; import from kfar
  1533. open2           dd      ?
  1534. filesize        dd      ?
  1535. read            dd      ?
  1536. seek            dd      ?
  1537. close           dd      ?
  1538. pgalloc         dd      ?
  1539. pgrealloc       dd      ?
  1540. pgfree          dd      ?
  1541. getfreemem      dd      ?
  1542. DialogBox       dd      ?
  1543. SayErr          dd      ?
  1544. Message         dd      ?
  1545. cur_console_size dd     ?
  1546.  
  1547. ; data for editbox in kfar dialog
  1548. password_maxlen = 512
  1549. password_data:
  1550. .maxlen         dd      ?
  1551. .pos            dd      ?
  1552. .start          dd      ?
  1553. password_ansi   rb      password_maxlen+1
  1554. bPasswordDefined db     ?
  1555.  
  1556. ; converted password
  1557. password_unicode rw     password_maxlen+1
  1558. password_size   dd      ?
  1559.  
  1560. IncludeUGlobals
  1561.  
  1562. bWasWarning     db      ?
  1563.