Subversion Repositories Kolibri OS

Rev

Rev 1022 | Rev 1148 | 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.16
  6. ; last update:          2009-07-03 (Jul 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://diamondz.land.ru
  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.         pop     ecx
  875.         pop     esi
  876. ; ecx = parent item, eax = current item
  877.         mov     [eax+file_common.name], esi
  878.         inc     dword [ecx+16]  ; new item in parent folder
  879.         push    ecx
  880. ; add new item to end of L2-list
  881.         and     [eax+file_common.next], 0
  882.         cmp     [eax+file_common.bIsDirectory], 0
  883.         jnz     @f
  884.         add     ecx, 8
  885. @@:
  886.         push    eax
  887.         sub     eax, [hOut]
  888.         cmp     dword [ecx], 0
  889.         jnz     @f
  890.         mov     [ecx], eax
  891. @@:
  892.         xchg    eax, [ecx+4]
  893.         xchg    eax, ecx
  894.         pop     eax
  895.         mov     [eax+file_common.prev], ecx
  896.         jecxz   @f
  897.         add     ecx, [hOut]
  898.         sub     eax, [hOut]
  899.         mov     [ecx+file_common.next], eax
  900.         add     eax, [hOut]
  901. @@:
  902.         pop     ecx
  903. ; set parent link
  904.         and     [eax+file_common.parent], 0
  905.         cmp     ecx, edi
  906.         jz      @f
  907.         sub     ecx, file_common.subfolders
  908.         sub     ecx, [hOut]
  909.         mov     [eax+file_common.parent], ecx
  910. @@:
  911. ; set current directory to current item
  912.         lea     ecx, [eax+file_common.subfolders]
  913. ; if that was not last component, continue parse name
  914.         add     esi, [eax+file_common.namelen]
  915.         lodsb
  916.         test    al, al
  917.         jnz     .parseloop
  918. .mainloopcont:
  919. ; continue main loop
  920.         add     edx, [esp+4]
  921.         jmp     .mainloop
  922. .mainloopdone:
  923. ; Loop done.
  924.         ret     4
  925.  
  926. ; This subroutine is called by getattr and open.
  927. ; This subroutine looks for file name and returns NULL or pointer to file info record.
  928. lookup_file_name:
  929.         mov     ebp, [esp+8]    ; hPlugin
  930.         mov     esi, [esp+12]   ; filename
  931.         lea     edi, [ebp+handle_common.root.subfolders]
  932.         xor     eax, eax
  933. ; KFar operates with absolute names, skip first '/'
  934.         cmp     byte [esi], '/'
  935.         jnz     .notfound
  936.         inc     esi
  937. .mainloop:
  938. ; get next component of name
  939.         push    -1
  940.         pop     ecx
  941. @@:
  942.         inc     ecx
  943.         cmp     byte [esi+ecx], '/'
  944.         jz      @f
  945.         cmp     byte [esi+ecx], 0
  946.         jnz     @b
  947. @@:
  948. ; esi->component, ecx=length
  949. ; scan for required item in subfolders list
  950.         push    -1
  951.         mov     eax, [edi]      ; .subfolders
  952. .scan1:
  953.         test    eax, eax
  954.         jz      .notfound1
  955.         add     eax, ebp
  956.         cmp     [eax+file_common.namelen], ecx
  957.         jnz     .cont1
  958.         push    ecx esi edi
  959.         mov     edi, [eax+file_common.name]
  960.         repz    cmpsb
  961.         pop     edi esi ecx
  962.         jz      .found1
  963. .cont1:
  964.         mov     eax, [eax+file_common.next]
  965.         jmp     .scan1
  966. .notfound1:
  967.         pop     edx
  968. ; if this is last component in file name, scan in subfiles list
  969.         cmp     byte [esi+ecx], al
  970.         jnz     .notfound
  971.         inc     edx
  972.         jnz     .notfound
  973.         mov     eax, [edi+8]    ; .subfiles
  974.         push    edx
  975.         jmp     .scan1
  976. .found1:
  977.         pop     edi
  978. ; item is found, go to next component
  979.         lea     edi, [eax+file_common.subfolders]
  980.         lea     esi, [esi+ecx+1]
  981.         cmp     byte [esi-1], 0
  982.         jnz     .mainloop
  983. ; this was the last component
  984. .notfound:
  985.         ret
  986.  
  987. ; Memory streams handling.
  988. ; Archive handlers create memory stream for small files:
  989. ; size of which is not greater than (free RAM size)/4 and
  990. ; not greater than following constant...
  991. ;LIMIT_FOR_MEM_STREAM = 2*1024*1024
  992. ; ...if it is defined. Now the definition is commented:
  993. ; if user has many physical memory, why not to use it?
  994.  
  995. virtual at 0
  996. mem_stream:
  997. .type   dd      ?       ; type_mem_stream
  998. .size   dd      ?
  999. .pos    dd      ?
  1000. .buf:
  1001. end virtual
  1002.  
  1003. ; unsigned __stdcall read(ebx = HANDLE hFile, void* buf, unsigned size);
  1004. read_mem_stream:
  1005.         mov     eax, [esp+12]
  1006.         mov     ecx, [ebx+mem_stream.size]
  1007.         sub     ecx, [ebx+mem_stream.pos]
  1008.         jnc     @f
  1009.         xor     ecx, ecx
  1010. @@:
  1011.         cmp     eax, ecx
  1012.         jb      @f
  1013.         mov     eax, ecx
  1014. @@:
  1015.         mov     ecx, eax
  1016.         lea     esi, [ebx+mem_stream.buf]
  1017.         add     esi, [ebx+mem_stream.pos]
  1018.         add     [ebx+mem_stream.pos], eax
  1019.         mov     edi, [esp+8]
  1020.         mov     edx, ecx
  1021.         shr     ecx, 2
  1022.         rep     movsd
  1023.         mov     ecx, edx
  1024.         and     ecx, 3
  1025.         rep     movsb
  1026.         ret     12
  1027.  
  1028. ; void __stdcall setpos(ebx = HANDLE hFile, __int64 pos);
  1029. setpos_mem_stream:
  1030.         mov     eax, [esp+8]
  1031.         mov     [ebx+mem_stream.pos], eax
  1032.         ret     12
  1033.  
  1034. ; void __stdcall close(ebx = HANDLE hFile);
  1035. close_mem_stream:
  1036.         mov     ecx, ebx
  1037.         call    [pgfree]
  1038.         ret     4
  1039.  
  1040. ; Allocate handle for file
  1041. ; esi -> handle table, ecx = size of handle
  1042. alloc_handle:
  1043. ; Handle table is L2-list of allocated pages.
  1044. ; Scan for free entry
  1045.         mov     edx, esi
  1046. @@:
  1047.         mov     edx, [edx]
  1048.         cmp     edx, esi
  1049.         jz      .alloc_new
  1050.         mov     eax, [edx+8]            ; head of L1-list of free entries
  1051.         test    eax, eax                ; has free entry?
  1052.         jz      @b
  1053. ; we have found allocated page with free entry; allocate entry and return
  1054.         inc     dword [edx+12]          ; number of busy entries
  1055.         push    dword [eax]
  1056.         pop     dword [edx+8]
  1057. .ret:
  1058.         ret
  1059. .alloc_new:
  1060. ; no free pages; get new page and initialize
  1061.         push    ecx
  1062.         mov     ecx, 0x1000
  1063.         call    [pgalloc]
  1064.         pop     ecx
  1065.         test    eax, eax
  1066.         jz      .ret
  1067. ; insert new page to start of L2-list
  1068.         mov     edx, [esi]
  1069.         mov     [eax], edx
  1070.         mov     [esi], eax
  1071.         mov     [eax+4], esi
  1072.         mov     [edx+4], eax
  1073.         mov     dword [eax+12], 1       ; 1 allocated entry
  1074. ; initialize list of free entries
  1075.         lea     edx, [eax+16]
  1076.         push    edx     ; save return value
  1077.         add     edx, ecx
  1078.         mov     [eax+8], edx
  1079.         add     eax, 0x1000
  1080. @@:
  1081.         mov     esi, edx
  1082.         add     edx, ecx
  1083.         mov     [esi], edx
  1084.         cmp     edx, eax
  1085.         jb      @b
  1086.         and     dword [esi], 0
  1087.         pop     eax
  1088.         ret
  1089.  
  1090. ; Free handle allocated in previous procedure
  1091. ; esi = handle
  1092. free_handle:
  1093.         mov     ecx, esi
  1094.         and     ecx, not 0xFFF  ; get page
  1095. ; add entry to head of L1-list of free entries
  1096.         mov     eax, [ecx+8]
  1097.         mov     [esi], eax
  1098.         mov     [ecx+8], esi
  1099.         dec     dword [ecx+12]  ; decrement number of allocated entries
  1100.         jnz     .ret
  1101. ; delete page from common L2-list
  1102.         mov     eax, [ecx]
  1103.         mov     edx, [ecx+4]
  1104.         mov     [eax+4], edx
  1105.         mov     [edx], eax
  1106. ; free page
  1107.         call    [pgfree]
  1108. .ret:
  1109.         ret
  1110.  
  1111. ; Ask user to enter password.
  1112. ; Out: ZF set <=> user pressed Esc
  1113. ;      'password_ansi', 'password_unicode', 'password_size' filled
  1114. query_password:
  1115.         cmp     [bPasswordDefined], 0
  1116.         jnz     .ret
  1117.         mov     edi, password_data
  1118.         mov     eax, password_maxlen
  1119.         stosd           ; maximum length
  1120.         xor     eax, eax
  1121.         stosd           ; start of visible part
  1122.         stosd           ; position of cursor
  1123.         stosb           ; initial state: empty string
  1124.         mov     eax, [cur_console_size]
  1125.         mov     eax, [eax]      ; get current console width
  1126.         sub     eax, 12
  1127.         mov     edi, password_dlg
  1128.         mov     [edi+password_dlg.width-password_dlg], eax
  1129.         dec     eax
  1130.         dec     eax
  1131.         mov     [edi+password_dlg.width1-password_dlg], eax
  1132.         mov     [edi+password_dlg.width2-password_dlg], eax
  1133.         push    edi
  1134.         call    [DialogBox]
  1135.         inc     eax
  1136.         jz      .ret
  1137. ; convert ANSI-cp866 to UNICODE string; also calculate 'password_size'
  1138.         mov     esi, password_ansi
  1139.         mov     edi, password_unicode
  1140.         or      [password_size], -1
  1141. .cvt:
  1142.         inc     [password_size]
  1143.         lodsb
  1144.         mov     ah, 0
  1145. ; 0x00-0x7F - trivial map
  1146.         cmp     al, 0x80
  1147.         jb      .symb
  1148. ; 0x80-0xAF -> 0x410-0x43F
  1149.         cmp     al, 0xB0
  1150.         jae     @f
  1151.         add     ax, 0x410-0x80
  1152.         jmp     .symb
  1153. @@:
  1154. ; 0xE0-0xEF -> 0x440-0x44F
  1155.         cmp     al, 0xE0
  1156.         jb      .unk
  1157.         cmp     al, 0xF0
  1158.         jae     @f
  1159.         add     ax, 0x440-0xE0
  1160.         jmp     .symb
  1161. @@:
  1162. ; 0xF0 -> 0x401
  1163. ; 0xF1 -> 0x451
  1164.         cmp     al, 'Ё'
  1165.         jz      .yo1
  1166.         cmp     al, 'ё'
  1167.         jz      .yo2
  1168. .unk:
  1169.         mov     al, '_'
  1170.         jmp     .symb
  1171. .yo1:
  1172.         mov     ax, 0x401
  1173.         jmp     .symb
  1174. .yo2:
  1175.         mov     ax, 0x451
  1176. .symb:
  1177.         stosw
  1178.         test    al, al
  1179.         jnz     .cvt
  1180.         inc     [bPasswordDefined]      ; clears ZF flag
  1181. .ret:
  1182.         ret
  1183.  
  1184. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1185. ;;;;;;;;;;;;; API for other programs ;;;;;;;;;;;;
  1186. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1187. ; void* __stdcall deflate_unpack(void* packed_data, unsigned* pLength)
  1188. deflate_unpack:
  1189.         push    dword [esp+8]
  1190.         push    esp
  1191.         push    deflate_unpack_cb
  1192.         call    deflate_unpack2
  1193.         ret     8
  1194.  
  1195. deflate_unpack_cb:
  1196.         mov     edx, [esp+4]
  1197.         push    edx
  1198.         mov     edx, [edx+12]
  1199.         mov     edx, [edx]
  1200.         mov     eax, [esp+8+4]
  1201.         mov     [eax], edx
  1202.         pop     edx
  1203.         xor     eax, eax
  1204.         xchg    eax, [edx+8]
  1205.         ret     8
  1206.  
  1207. ; void* __stdcall deflate_unpack2(void* get_next_chunk, void* parameter, unsigned* pUnpackedLength)
  1208. ;       void* __stdcall get_next_chunk(void* parameter, unsigned* pLength)
  1209. deflate_unpack2:
  1210.         pusha
  1211.         mov     ecx, 0x11000
  1212.         call    mypgalloc
  1213.         test    eax, eax
  1214.         jz      .ret
  1215.         or      dword [eax+streamInfo.fullSize], -1
  1216.         or      dword [eax+streamInfo.fullSize+4], -1
  1217.         and     dword [eax+streamInfo.bufSize], 0
  1218.         mov     dword [eax+streamInfo.fillBuf], .fillBuf
  1219.         mov     edx, [esp+32+4]
  1220.         mov     [eax+streamInfo.size], edx
  1221.         mov     edx, [esp+32+8]
  1222.         mov     [eax+streamInfo.size+4], edx
  1223.         mov     [eax+streamInfo.size+8+deflate_decoder.inStream], eax
  1224.         add     eax, streamInfo.size+8
  1225.         lea     edi, [eax+deflate_decoder.size]
  1226.         mov     [eax+streamInfo.bufPtr], edi
  1227.         mov     ebp, eax
  1228.         call    deflate_init_decoder
  1229.         xor     edx, edx
  1230.         mov     ecx, 10000h
  1231. .loop:
  1232.         push    @f
  1233.         pushad
  1234.         mov     [_esp], esp
  1235.         mov     [_ebp], ebp
  1236.         mov     [error_proc], .error
  1237.         mov     ecx, 10000h
  1238.         jmp     [eax+streamInfo.fillBuf]
  1239. @@:
  1240.         push    68
  1241.         pop     eax
  1242.         push    20
  1243.         pop     ebx
  1244.         int     0x40
  1245.         test    eax, eax
  1246.         jz      .nomem
  1247.         mov     edx, eax
  1248.         mov     eax, ebp
  1249.         mov     esi, edi
  1250.         push    edi
  1251.         lea     edi, [edx+ecx-0x10000]
  1252.         push    ecx
  1253.         mov     ecx, 0x10000/4
  1254.         rep     movsd
  1255.         pop     ecx
  1256.         pop     edi
  1257.         add     ecx, 0x10000
  1258.         jmp     .loop
  1259. .error:
  1260.         pop     eax
  1261.         push    edi
  1262.         popad
  1263.         pop     eax
  1264.         mov     eax, ebp
  1265.         lea     esi, [eax+deflate_decoder.size]
  1266.         sub     ecx, 0x10000
  1267.         sub     edi, esi
  1268.         add     ecx, edi
  1269.         mov     eax, [esp+32+12]
  1270.         test    eax, eax
  1271.         jz      @f
  1272.         mov     [eax], ecx
  1273. @@:
  1274.         test    ecx, ecx
  1275.         jnz     @f
  1276.         inc     ecx
  1277. @@:
  1278.         push    68
  1279.         pop     eax
  1280.         push    20
  1281.         pop     ebx
  1282.         int     0x40
  1283.         test    eax, eax
  1284.         jz      .nomem
  1285.         sub     ecx, edi
  1286.         mov     edx, edi
  1287.         lea     edi, [eax+ecx]
  1288.         mov     ecx, edx
  1289.         shr     ecx, 2
  1290.         rep     movsd
  1291.         mov     ecx, edx
  1292.         and     ecx, 3
  1293.         rep     movsb
  1294.         push    eax
  1295.         push    68
  1296.         pop     eax
  1297.         push    13
  1298.         pop     ebx
  1299.         lea     ecx, [ebp-streamInfo.size-8]
  1300.         int     40h
  1301.         pop     eax
  1302.         jmp     .ret
  1303. .nomem:
  1304.         push    68
  1305.         pop     eax
  1306.         push    13
  1307.         pop     ebx
  1308.         test    edx, edx
  1309.         jz      @f
  1310.         mov     ecx, edx
  1311.         push    eax
  1312.         int     0x40
  1313.         pop     eax
  1314. @@:
  1315.         lea     ecx, [ebp-streamInfo.size-8]
  1316.         int     0x40
  1317.         xor     eax, eax
  1318. .ret:
  1319.         mov     [esp+28], eax
  1320.         popa
  1321.         ret     12
  1322. .fillBuf:
  1323.         push    eax
  1324.         push    eax
  1325.         push    esp
  1326.         push    dword [eax+streamInfo.size+4]
  1327.         call    dword [eax+streamInfo.size]
  1328.         pop     edx
  1329.         pop     ebp
  1330.         mov     [ebp+streamInfo.bufPtr], eax
  1331.         and     [ebp+streamInfo.bufDataLen], 0
  1332.         test    eax, eax
  1333.         jz      @f
  1334.         mov     [ebp+streamInfo.bufDataLen], edx
  1335. @@:
  1336.         popad
  1337.         ret
  1338.  
  1339. mypgalloc:
  1340.         push    68
  1341.         pop     eax
  1342.         push    12
  1343.         pop     ebx
  1344.         int     0x40
  1345.         ret
  1346.  
  1347. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1348. ;;;;;;;;;;;;;;;; Initialized data ;;;;;;;;;;;;;;;
  1349. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1350.  
  1351. ; export table
  1352. align 4
  1353. EXPORTS:
  1354.         dd      aVersion,       3
  1355.         dd      aPluginLoad,    plugin_load
  1356.         dd      aOpenFilePlugin,OpenFilePlugin
  1357.         dd      aClosePlugin,   ClosePlugin
  1358.         dd      aReadFolder,    ReadFolder
  1359.         dd      aSetFolder,     SetFolder
  1360.         dd      aGetFiles,      GetFiles
  1361.         dd      aGetOpenPluginInfo, GetOpenPluginInfo
  1362.         dd      aGetattr,       mygetattr
  1363.         dd      aOpen,          myopen
  1364.         dd      aRead,          myread
  1365.         dd      aSetpos,        mysetpos
  1366.         dd      aClose,         myclose
  1367.         dd      aDeflateUnpack, deflate_unpack
  1368.         dd      aDeflateUnpack2,deflate_unpack2
  1369.         dd      0
  1370.  
  1371. ; exported names
  1372. aVersion        db      'version',0
  1373. aPluginLoad     db      'plugin_load',0
  1374. aOpenFilePlugin db      'OpenFilePlugin',0
  1375. aClosePlugin    db      'ClosePlugin',0
  1376. aReadFolder     db      'ReadFolder',0
  1377. aSetFolder      db      'SetFolder',0
  1378. aGetFiles       db      'GetFiles',0
  1379. aGetOpenPluginInfo db   'GetOpenPluginInfo',0
  1380. aGetattr        db      'getattr',0
  1381. aOpen           db      'open',0
  1382. aRead           db      'read',0
  1383. aSetpos         db      'setpos',0
  1384. aClose          db      'close',0
  1385. aDeflateUnpack  db      'deflate_unpack',0
  1386. aDeflateUnpack2 db      'deflate_unpack2',0
  1387.  
  1388. ; common strings
  1389. if lang eq ru
  1390. aContinue       db      'Продолжить',0
  1391. aCancel         db      'Отмена',0
  1392. aHeaderError    db      'Ошибка в заголовке архива',0
  1393. aReadError      db      'Ошибка чтения',0
  1394. aNoFreeRam      db      'Недостаточно свободной оперативной памяти',0
  1395. aEncodingProblem db     'Проблема с кодировкой',0
  1396. aEncodingProblem_str db 'Имена некоторых файлов в архиве содержат символы,',0
  1397. .2              db      'не представимые в кодировке cp866.',0
  1398. .3              db      'Эти символы будут заменены на подчёркивания.',0
  1399. aEnterPassword  db      'Введите пароль:',0
  1400. aEnterPasswordLen = $ - aEnterPassword - 1
  1401. aEnterPasswordTitle db  'Ввод пароля',0
  1402. aArchiveDataError db    'Ошибка в данных архива',0
  1403. aArchiveDataErrorPass db 'Ошибка в данных архива или неверный пароль',0
  1404. aChangePass     db      'Ввести пароль',0
  1405. aNameTooLong    db      'Слишком длинное имя',0
  1406. aCannotOpenFile db      'Не могу открыть файл',0
  1407. else
  1408. aContinue       db      'Continue',0
  1409. aCancel         db      'Cancel',0
  1410. aHeaderError    db      'Invalid archive header',0
  1411. aReadError      db      'Read error',0
  1412. aNoFreeRam      db      'There is not enough of free RAM',0
  1413. aEncodingProblem db     'Encoding problem',0
  1414. aEncodingProblem_str db 'The names of some files in the archive contain',0
  1415. .2              db      'characters which can not be represented in cp866.',0
  1416. .3              db      'Such characters will be replaced to underscores.',0
  1417. aEnterPassword  db      'Enter password:',0
  1418. aEnterPasswordLen = $ - aEnterPassword - 1
  1419. aEnterPasswordTitle db  'Get password',0
  1420. aArchiveDataError db    'Error in archive data',0
  1421. aArchiveDataErrorPass db 'Error in archive data or incorrect password',0
  1422. aChangePass     db      'Enter password',0
  1423. aNameTooLong    db      'Name is too long',0
  1424. aCannotOpenFile db      'Cannot open file',0
  1425. end if
  1426.  
  1427. ; kfar_arc supports many archive types.
  1428. ; OpenFilePlugin looks for supported archive signature and gives control
  1429. ;   to concrete handler if found.
  1430. ; Other functions just determine type of opened archive and jump to corresponding handler.
  1431. type_mem_stream = 0     ; memory stream - for file handles (returned from 'open')
  1432. type_7z = 1
  1433. type_zip = 2
  1434.  
  1435. ; archive functions (types start from type_7z)
  1436. align 4
  1437. ClosePluginTable:
  1438.         dd      close_7z
  1439.         dd      close_zip
  1440. getattrTable:
  1441.         dd      getattr_7z
  1442.         dd      getattr_zip
  1443. openTable:
  1444.         dd      open_file_7z
  1445.         dd      open_file_zip
  1446. basesizes:
  1447.         dd      handle_7z.basesize, file_in_7z.size
  1448.         dd      handle_zip.basesize, file_in_zip.size
  1449.  
  1450. ; file functions (types start from type_mem_stream)
  1451. readTable:
  1452.         dd      read_mem_stream
  1453.         dd      read_7z
  1454.         dd      read_zip
  1455. setposTable:
  1456.         dd      setpos_mem_stream
  1457.         dd      setpos_7z
  1458.         dd      setpos_zip
  1459. closeTable:
  1460.         dd      close_mem_stream
  1461.         dd      close_file_7z
  1462.         dd      close_file_zip
  1463.  
  1464. ; pointers for SayErr and Message
  1465. ContinueBtn     dd      aContinue
  1466. HeaderError_ptr dd      aHeaderError
  1467. aReadError_ptr  dd      aReadError
  1468. aNoFreeRam_ptr  dd      aNoFreeRam
  1469. aEncodingProblem_str_ptr:
  1470.                 dd      aEncodingProblem_str
  1471.                 dd      aEncodingProblem_str.2
  1472.                 dd      aEncodingProblem_str.3
  1473. aNameTooLong_ptr dd     aNameTooLong
  1474. aArchiveDataError_ptr dd aArchiveDataError
  1475. aArchiveDataErrorPass_ptr dd aArchiveDataErrorPass
  1476. CancelPassBtn   dd      aCancel
  1477.                 dd      aChangePass
  1478.  
  1479. ; "enter password" dialog for KFar
  1480. password_dlg:
  1481.         dd      1       ; use standard dialog colors
  1482.         dd      -1      ; center window by x
  1483.         dd      -1      ; center window by y
  1484. .width  dd      ?       ; width (will be filled according to current console width)
  1485.         dd      2       ; height
  1486.         dd      4, 2    ; border size
  1487.         dd      aEnterPasswordTitle     ; title
  1488.         dd      ?       ; colors (will be set by KFar)
  1489.         dd      0       ; used internally by dialog manager, ignored
  1490.         dd      0, 0    ; reserved for DlgProc
  1491.         dd      2       ; 2 controls
  1492. ; the string "enter password"
  1493.         dd      1       ; type: static
  1494.         dd      1,0     ; upper-left position
  1495. .width1 dd      ?,0     ; bottom-right position
  1496.         dd      aEnterPassword  ; data
  1497.         dd      0       ; flags
  1498. ; editbox for password
  1499.         dd      3       ; type: edit
  1500.         dd      1,1     ; upper-left position
  1501. .width2 dd      ?,0     ; bottom-right position
  1502.         dd      password_data   ; data
  1503.         dd      2Ch     ; flags
  1504.  
  1505. IncludeIGlobals
  1506.  
  1507. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1508. ;;;;;;;;;;;;;;; Uninitialized data ;;;;;;;;;;;;;;
  1509. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1510.  
  1511. section '.udata' data readable writable align 16
  1512. kfar_info       dd      ?
  1513. crc_table       rd      256
  1514. _esp            dd      ?
  1515. _ebp            dd      ?
  1516. bufsize         dd      ?
  1517. bufptr          dd      ?
  1518. bufend          dd      ?
  1519. buffer          rb      1024
  1520. inStream        dd      ?
  1521. hOut            dd      ?
  1522. .allocated      dd      ?
  1523.  
  1524. error_proc      dd      ?
  1525. clear_proc      dd      ?
  1526.  
  1527. ; import from kfar
  1528. open2           dd      ?
  1529. filesize        dd      ?
  1530. read            dd      ?
  1531. seek            dd      ?
  1532. close           dd      ?
  1533. pgalloc         dd      ?
  1534. pgrealloc       dd      ?
  1535. pgfree          dd      ?
  1536. getfreemem      dd      ?
  1537. DialogBox       dd      ?
  1538. SayErr          dd      ?
  1539. Message         dd      ?
  1540. cur_console_size dd     ?
  1541.  
  1542. ; data for editbox in kfar dialog
  1543. password_maxlen = 512
  1544. password_data:
  1545. .maxlen         dd      ?
  1546. .pos            dd      ?
  1547. .start          dd      ?
  1548. password_ansi   rb      password_maxlen+1
  1549. bPasswordDefined db     ?
  1550.  
  1551. ; converted password
  1552. password_unicode rw     password_maxlen+1
  1553. password_size   dd      ?
  1554.  
  1555. IncludeUGlobals
  1556.  
  1557. bWasWarning     db      ?
  1558.