Subversion Repositories Kolibri OS

Rev

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