Subversion Repositories Kolibri OS

Rev

Rev 631 | 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.1
  6. ; last update:          2007-07-11 (Jul 11, 2007)
  7. ; minimal KFar version: 0.4
  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.  
  34. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  35. ;;;;;;;;;;;;;;; Interface for KFar ;;;;;;;;;;;;;;
  36. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  37. virtual at 0
  38. kfar_info_struc:
  39. .lStructSize    dd      ?
  40. .kfar_ver       dd      ?
  41. .open           dd      ?
  42. .read           dd      ?
  43. .write          dd      ?
  44. .seek           dd      ?
  45. .flush          dd      ?
  46. .filesize       dd      ?
  47. .close          dd      ?
  48. .pgalloc        dd      ?
  49. .pgrealloc      dd      ?
  50. .pgfree         dd      ?
  51. .getfreemem     dd      ?
  52. .pgalloc2       dd      ?
  53. .pgrealloc2     dd      ?
  54. .pgfree2        dd      ?
  55. .menu           dd      ?
  56. .menu_centered_in dd    ?
  57. .DialogBox      dd      ?
  58. .SayErr         dd      ?
  59. .Message        dd      ?
  60. .cur_console_size dd    ?
  61. end virtual
  62.  
  63. ; int __stdcall plugin_load(kfar_info* info);
  64. ; Initialization of plugin + Save used KFar functions.
  65. plugin_load:
  66.         mov     eax, [esp+4]
  67.         mov     [kfar_info], eax
  68.         push    [eax+kfar_info_struc.read]
  69.         pop     [read]
  70.         push    [eax+kfar_info_struc.seek]
  71.         pop     [seek]
  72.         push    [eax+kfar_info_struc.close]
  73.         pop     [close]
  74.         lea     esi, [eax+kfar_info_struc.DialogBox]
  75.         mov     edi, DialogBox
  76.         movsd
  77.         movsd
  78.         movsd
  79.         movsd
  80.         lea     esi, [eax+kfar_info_struc.pgalloc]
  81.         mov     edi, pgalloc
  82.         movsd
  83.         movsd
  84.         movsd
  85.         movsd
  86.         call    init_crc_table
  87.         call    init_aes
  88.         call    init_ppmd
  89.         xor     eax, eax        ; success
  90.         ret     4
  91.  
  92. ; HANDLE __stdcall OpenFilePlugin(HANDLE basefile, const char* name,
  93. ;       const void* attr, const void* data, int datasize);
  94. ; This function is called when user presses Enter (or Ctrl+PgDn) on file.
  95. ; Plugin tests whether given file is of supported type
  96. ;   and if so, loads information and returns
  97. ;   handle to be used in subsequent calls to ReadFolder, SetFolder and so on.
  98. OpenFilePlugin:
  99.         mov     [bPasswordDefined], 0
  100.         mov     esi, [esp+16]
  101.         mov     ebp, [esp+4]
  102. ; test for 7z archive
  103.         cmp     dword [esp+20], 20h     ; minimal size of 7z archive is 20h bytes
  104.         jb      .no_7z
  105.         cmp     word [esi], '7z'                ; signature, part 1
  106.         jnz     .no_7z
  107.         cmp     dword [esi+2], 0x1C27AFBC       ; signature, part 2
  108.         jnz     .no_7z
  109.         call    open_7z
  110.         ret     20
  111. .no_7z:
  112.         xor     eax, eax
  113.         ret     20
  114.  
  115. ; Handle of plugin in kfar_arc is as follow:
  116. virtual at 0
  117. handle_common:
  118. .type           dd      ?
  119. .root.subfolders        dd      ?
  120. .root.subfolders.end    dd      ?
  121. .root.subfiles          dd      ?
  122. .root.subfiles.end      dd      ?
  123. .root.NumSubItems       dd      ?
  124. ; ... some plugin-specific data follows ...
  125. end virtual
  126.  
  127. ; and for each archive item there is one file info structure, which begins as follow:
  128. virtual at 0
  129. file_common:
  130. .fullname       dd      ?       ; pointer to cp866 string
  131. .name           dd      ?       ; name without path (end of .fullname)
  132. .namelen        dd      ?       ; strlen(.name)
  133. .bIsDirectory   db      ?
  134. .bPseudoFolder  db      ?
  135.                 rb      2
  136. .parent         dd      ?       ; pointer to parent directory record
  137. .subfolders     dd      ?       ; head of L2-list of subfolders [for folders]
  138. .subfolders.end dd      ?
  139. .subfiles       dd      ?       ; head of L2-list of files [for folders]
  140. .subfiles.end   dd      ?
  141. .NumSubItems    dd      ?
  142. .next           dd      ?       ; next item in list of subfolders/files
  143. .prev           dd      ?       ; previous item in list of subfolders/files
  144. end virtual
  145.  
  146. ; void __stdcall ClosePlugin(HANDLE hPlugin);
  147. ; This function frees all resources allocated in OpenFilePlugin.
  148. ClosePlugin:
  149.         mov     eax, [esp+4]    ; get hPlugin
  150.         mov     eax, [eax]      ; hPlugin is pointer to internal data structure
  151.                                 ; first dword is archive type (type_xxx constants)
  152.         dec     eax             ; types start from 1
  153.         jmp     dword [ClosePluginTable+eax*4]
  154.  
  155. ; int __stdcall ReadFolder(HANDLE hPlugin,
  156. ;       unsigned dirinfo_start, unsigned dirinfo_size, void* dirdata);
  157. ReadFolder:
  158.         mov     eax, [esp+4]
  159.         mov     eax, [eax]
  160.         dec     eax
  161.         jmp     dword [ReadFolderTable+eax*4]
  162.  
  163. ; bool __stdcall SetFolder(HANDLE hPlugin,
  164. ;       const char* relative_path, const char* absolute_path);
  165. SetFolder:
  166.         mov     eax, [esp+4]
  167.         mov     eax, [eax]
  168.         dec     eax
  169.         jmp     dword [SetFolderTable+eax*4]
  170.  
  171. ; void __stdcall GetFiles(HANDLE hPlugin, int NumItems, void* items[],
  172. ;       void* addfile, void* adddir);
  173. ;       bool __stdcall addfile(const char* name, void* bdfe_info, HANDLE hFile);
  174. ;       bool __stdcall adddir(const char* name, void* bdfe_info);
  175. GetFiles:
  176.         mov     ebp, [esp+4]
  177.         mov     eax, [ebp]
  178.         dec     eax
  179.         jmp     dword [GetFilesTable+eax*4]
  180.  
  181. ; void __stdcall GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo* info);
  182. GetOpenPluginInfo:
  183.         mov     eax, [esp+8]    ; get info ptr
  184.         mov     byte [eax], 3   ; flags: add non-existing '..' entry automatically
  185.                                 ;        use GetFiles for copying
  186.         ret     8
  187.  
  188. ; int __stdcall getattr(HANDLE hPlugin, const char* filename, void* info);
  189. mygetattr:
  190.         call    lookup_file_name
  191.         test    eax, eax
  192.         jz      @f
  193.         mov     edx, [ebp]
  194.         dec     edx
  195.         mov     edi, [esp+12]   ; info ptr
  196.         call    dword [getattrTable+edx*4]
  197.         xor     eax, eax
  198.         ret     12
  199. @@:
  200.         mov     al, 5   ; ERROR_FILE_NOT_FOUND
  201.         ret     12
  202.  
  203. ; HANDLE __stdcall open(HANDLE hPlugin, const char* filename, int mode);
  204. myopen:
  205.         call    lookup_file_name
  206.         test    eax, eax
  207.         jz      @f
  208.         mov     edx, [ebp]
  209.         dec     edx
  210.         mov     edi, [esp+12]   ; mode
  211.         call    dword [openTable+edx*4]
  212. @@:
  213.         ret     12
  214.  
  215. ; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
  216. myread:
  217.         mov     ebx, [esp+4]
  218.         mov     eax, [ebx]
  219.         jmp     dword [readTable+eax*4]
  220.  
  221. ; void __stdcall setpos(HANDLE hFile, __int64 pos);
  222. mysetpos:
  223.         mov     ebx, [esp+4]
  224.         mov     eax, [ebx]
  225.         jmp     dword [setposTable+eax*4]
  226.  
  227. ; void __stdcall close(HANDLE hFile);
  228. myclose:
  229.         mov     ebx, [esp+4]
  230.         mov     eax, [ebx]
  231.         jmp     dword [closeTable+eax*4]
  232.  
  233. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  234. ;;;;;;;;;;;;;; Auxiliary procedures ;;;;;;;;;;;;;
  235. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  236.  
  237. ; return.err and return.clear are labels to jmp if something is invalid
  238. ; the caller must previously define [_esp], [_ebp] and [error_proc], [clear_proc]
  239. return.err:
  240.         mov     esp, [_esp]
  241.         mov     ebp, [_ebp]
  242.         jmp     [error_proc]
  243. return.clear:
  244.         mov     esp, [_esp]
  245.         mov     ebp, [_ebp]
  246.         jmp     [clear_proc]
  247.  
  248. ; data for following routine
  249. iglobal
  250. align 4
  251. _24             dd      24
  252. _60             dd      60
  253. _10000000       dd      10000000
  254. days400year     dd      365*400+100-4+1
  255. days100year     dd      365*100+25-1
  256. days4year       dd      365*4+1
  257. days1year       dd      365
  258. months          dd      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  259. months2         dd      31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  260. _400            dd      400
  261. _100            dd      100
  262. endg
  263.  
  264. ; Convert QWORD FILETIME to BDFE format.
  265. ntfs_datetime_to_bdfe:
  266. ; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
  267.         push    eax
  268.         mov     eax, edx
  269.         xor     edx, edx
  270.         div     [_10000000]
  271.         xchg    eax, [esp]
  272.         div     [_10000000]
  273.         pop     edx
  274. ; edx:eax = number of seconds since January 1, 1601
  275.         push    eax
  276.         mov     eax, edx
  277.         xor     edx, edx
  278.         div     [_60]
  279.         xchg    eax, [esp]
  280.         div     [_60]
  281.         mov     [edi], dl
  282.         pop     edx
  283. ; edx:eax = number of minutes
  284.         div     [_60]
  285.         mov     [edi+1], dl
  286. ; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
  287.         xor     edx, edx
  288.         div     [_24]
  289.         mov     [edi+2], dl
  290.         mov     [edi+3], byte 0
  291. ; eax = number of days since January 1, 1601
  292.         xor     edx, edx
  293.         div     [days400year]
  294.         imul    eax, 400
  295.         add     eax, 1601
  296.         mov     [edi+6], ax
  297.         mov     eax, edx
  298.         xor     edx, edx
  299.         div     [days100year]
  300.         cmp     al, 4
  301.         jnz     @f
  302.         dec     eax
  303.         add     edx, [days100year]
  304. @@:
  305.         imul    eax, 100
  306.         add     [edi+6], ax
  307.         mov     eax, edx
  308.         xor     edx, edx
  309.         div     [days4year]
  310.         shl     eax, 2
  311.         add     [edi+6], ax
  312.         mov     eax, edx
  313.         xor     edx, edx
  314.         div     [days1year]
  315.         cmp     al, 4
  316.         jnz     @f
  317.         dec     eax
  318.         add     edx, [days1year]
  319. @@:
  320.         add     [edi+6], ax
  321.         push    esi edx
  322.         mov     esi, months
  323.         movzx   eax, word [edi+6]
  324.         test    al, 3
  325.         jnz     .noleap
  326.         xor     edx, edx
  327.         push    eax
  328.         div     [_400]
  329.         pop     eax
  330.         test    edx, edx
  331.         jz      .leap
  332.         xor     edx, edx
  333.         div     [_100]
  334.         test    edx, edx
  335.         jz      .noleap
  336. .leap:
  337.         mov     esi, months2
  338. .noleap:
  339.         pop     edx
  340.         xor     eax, eax
  341.         inc     eax
  342. @@:
  343.         sub     edx, [esi]
  344.         jb      @f
  345.         add     esi, 4
  346.         inc     eax
  347.         jmp     @b
  348. @@:
  349.         add     edx, [esi]
  350.         pop     esi
  351.         inc     edx
  352.         mov     [edi+4], dl
  353.         mov     [edi+5], al
  354.         add     edi, 8
  355.         ret
  356.  
  357. ; By given array of files information, initialize links between them
  358. ; ("[folder] contains [item]" relations).
  359. ; Information structure must be compatible with 'file_common'.
  360. ; Size of information structure is in [esp+4].
  361. init_file_links:
  362. ; in: edx->file infos, ebx = number of files, [esp+4] = size,
  363. ;     edi->{dd root.subfolders, dd root.subfolders.end,
  364. ;           dd root.subfiles, dd root.subfiles.end, dd root.NumItems}
  365.         xor     eax, eax
  366.         mov     [.free], eax
  367.         push    edi
  368.         stosd
  369.         stosd
  370.         stosd
  371.         stosd
  372.         stosd
  373.         pop     edi
  374. ; Loop through all files
  375. .mainloop:
  376.         dec     ebx
  377.         js      .mainloopdone
  378. ; Parse file name
  379. ; esi->current character in name
  380. ; dword [esp] = start of current component in file name
  381. ; ecx->{dd curdir.subfolders, dd curdir.subfolders.end,
  382. ;       dd curdir.subfiles, dd curdir.subfiles.end}
  383.         mov     esi, [edx+file_common.fullname]
  384.         mov     ecx, edi
  385. .parseloop:
  386.         push    esi
  387. .parsename:
  388.         lodsb
  389.         test    al, al
  390.         jz      @f
  391.         cmp     al, '/'
  392.         jnz     .parsename
  393. @@:
  394. ; we have found next component of current name; look for it in current directory
  395.         sub     esi, [esp]
  396.         dec     esi     ; esi = strlen(component)
  397.         cmp     esi, 259
  398.         jbe     @f
  399.         push    ContinueBtn
  400.         push    1
  401.         push    aNameTooLong_ptr
  402.         push    1
  403.         call    [SayErr]
  404.         jmp     return.clear
  405. @@:
  406.         push    ecx
  407.         mov     eax, [ecx]      ; eax->subfolders list
  408.         mov     ecx, esi
  409. .scansubfolders:
  410.         test    eax, eax
  411.         jz      .nofolder
  412.         add     eax, [hOut]
  413.         cmp     [eax+file_common.namelen], ecx
  414.         jnz     .scancont
  415.         mov     esi, [esp+4]
  416.         push    ecx edi
  417.         mov     edi, [eax+file_common.name]
  418.         repz    cmpsb
  419.         pop     edi ecx
  420.         jz      .subfound
  421. .scancont:
  422.         mov     eax, [eax+file_common.next]
  423.         jmp     .scansubfolders
  424. .subfound:
  425. ; found subfolder, set it as current and continue parsing name
  426.         add     [esp+4], ecx
  427.         pop     ecx
  428.         lea     ecx, [eax+file_common.subfolders]
  429.         pop     esi
  430.         lodsb
  431.         test    al, al
  432.         jnz     .parseloop
  433. ; that was the last component of the name, and we have found subfolder
  434. ; so found subfolder is a virtual subfolder and must be replaced with current
  435. ; name
  436.         mov     eax, [ecx-file_common.subfolders+file_common.namelen]
  437.         mov     [edx+file_common.namelen], eax
  438.         sub     esi, eax
  439.         dec     esi
  440.         mov     [edx+file_common.name], esi
  441.         sub     edx, [hOut]     ; convert pointer to relative
  442. ; replace item in L2-list
  443.         mov     eax, [ecx-file_common.subfolders+file_common.prev]
  444.         test    eax, eax
  445.         jnz     .1
  446.         mov     eax, [ecx-file_common.subfolders+file_common.parent]
  447.         sub     eax, file_common.next - file_common.subfolders
  448.         jnc     .1
  449.         lea     eax, [edi-file_common.next]
  450.         jmp     .2
  451. .1:
  452.         add     eax, [hOut]
  453. .2:
  454.         mov     [eax+file_common.next], edx
  455.         mov     eax, [ecx-file_common.subfolders+file_common.next]
  456.         test    eax, eax
  457.         jnz     .3
  458.         mov     eax, [ecx-file_common.subfolders+file_common.parent]
  459.         sub     eax, file_common.prev - file_common.subfolders.end
  460.         jnc     .3
  461.         lea     eax, [edi-file_common.prev+4]
  462.         jmp     .4
  463. .3:
  464.         add     eax, [hOut]
  465. .4:
  466.         mov     [eax+file_common.prev], edx
  467. ; correct parent links in childrens
  468.         mov     eax, [ecx]
  469. @@:
  470.         test    eax, eax
  471.         jz      @f
  472.         add     eax, [hOut]
  473.         mov     [eax+file_common.parent], edx
  474.         mov     eax, [eax+file_common.next]
  475.         jmp     @b
  476. @@:
  477.         mov     eax, [ecx+8]
  478. @@:
  479.         test    eax, eax
  480.         jz      @f
  481.         add     eax, [hOut]
  482.         mov     [eax+file_common.parent], edx
  483.         mov     eax, [eax+file_common.next]
  484.         jmp     @b
  485. @@:
  486.         add     edx, [hOut]
  487. ; set children links
  488.         mov     eax, [ecx]
  489.         mov     [edx+file_common.subfolders], eax
  490.         mov     eax, [ecx+4]
  491.         mov     [edx+file_common.subfolders.end], eax
  492.         mov     eax, [ecx+8]
  493.         mov     [edx+file_common.subfiles], eax
  494.         mov     eax, [ecx+12]
  495.         mov     [edx+file_common.subfiles.end], eax
  496.         mov     eax, [ecx+16]
  497.         mov     [edx+file_common.NumSubItems], eax
  498. ; set prev/next links
  499.         mov     eax, [ecx-file_common.subfolders+file_common.next]
  500.         mov     [edx+file_common.next], eax
  501.         mov     eax, [ecx-file_common.subfolders+file_common.prev]
  502.         mov     [edx+file_common.prev], eax
  503. ; add old item to list of free items
  504. uglobal
  505. align 4
  506. init_file_links.free    dd      ?
  507. endg
  508.         sub     ecx, file_common.subfolders
  509.         mov     eax, [.free]
  510.         mov     [ecx], eax
  511.         sub     ecx, [hOut]
  512.         mov     [.free], ecx
  513.         jmp     .mainloopcont
  514. .nofolder:
  515.         mov     eax, edx
  516.         mov     esi, [esp+4]
  517.         cmp     byte [esi+ecx], 0
  518.         jz      .newitem
  519. ; the current item is as 'dir1/item1' and 'dir1' has not been found
  520. ; allocate virtual subfolder 'dir1'
  521.         mov     eax, [init_file_links.free]
  522.         test    eax, eax
  523.         jz      .realloc
  524.         add     eax, [hOut]
  525.         push    dword [eax]
  526.         pop     [init_file_links.free]
  527.         jmp     .allocated
  528. .realloc:
  529. ; there is no free space, so reallocate [hOut] block
  530.         mov     eax, [hOut]
  531.         sub     [esp], eax      ; make pointers relative
  532.         sub     edx, eax
  533.         sub     edi, eax
  534.         push    ecx
  535.         mov     ecx, [hOut.allocated]
  536.         add     ecx, [esp+12+4]
  537.         mov     [hOut.allocated], ecx
  538.         push    ecx
  539.         and     ecx, 0xFFF
  540.         cmp     ecx, [esp+16+4]
  541.         pop     ecx
  542.         ja      @f
  543.         push    edx
  544.         mov     edx, eax
  545.         call    [pgrealloc]
  546.         pop     edx
  547.         test    eax, eax
  548.         jnz     @f
  549.         mov     ecx, [hOut]
  550.         call    [pgfree]
  551.         mov     esp, [_esp]
  552.         or      eax, -1
  553.         ret
  554. @@:
  555.         pop     ecx
  556.         mov     [hOut], eax
  557.         add     [esp], eax      ; make pointers absolute
  558.         add     edx, eax
  559.         add     edi, eax
  560.         add     eax, [hOut.allocated]
  561.         sub     eax, [esp+8+4]
  562. .allocated:
  563. ; eax -> new item
  564.         mov     [eax+file_common.bIsDirectory], 1
  565.         mov     [eax+file_common.bPseudoFolder], 1
  566. .newitem:
  567.         mov     [eax+file_common.namelen], ecx
  568.         pop     ecx
  569.         pop     esi
  570. ; ecx = parent item, eax = current item
  571.         mov     [eax+file_common.name], esi
  572.         inc     dword [ecx+16]  ; new item in parent folder
  573.         push    ecx
  574. ; add new item to end of L2-list
  575.         and     [eax+file_common.next], 0
  576.         cmp     [eax+file_common.bIsDirectory], 0
  577.         jnz     @f
  578.         add     ecx, 8
  579. @@:
  580.         push    eax
  581.         sub     eax, [hOut]
  582.         cmp     dword [ecx], 0
  583.         jnz     @f
  584.         mov     [ecx], eax
  585. @@:
  586.         xchg    eax, [ecx+4]
  587.         xchg    eax, ecx
  588.         pop     eax
  589.         mov     [eax+file_common.prev], ecx
  590.         jecxz   @f
  591.         add     ecx, [hOut]
  592.         sub     eax, [hOut]
  593.         mov     [ecx+file_common.next], eax
  594.         add     eax, [hOut]
  595. @@:
  596.         pop     ecx
  597. ; set parent link
  598.         and     [eax+file_common.parent], 0
  599.         cmp     ecx, edi
  600.         jz      @f
  601.         sub     ecx, file_common.subfolders
  602.         sub     ecx, [hOut]
  603.         mov     [eax+file_common.parent], ecx
  604. @@:
  605. ; set current directory to current item
  606.         lea     ecx, [eax+file_common.subfolders]
  607. ; if that was not last component, continue parse name
  608.         add     esi, [eax+file_common.namelen]
  609.         lodsb
  610.         test    al, al
  611.         jnz     .parseloop
  612. .mainloopcont:
  613. ; continue main loop
  614.         add     edx, [esp+4]
  615.         jmp     .mainloop
  616. .mainloopdone:
  617. ; Loop done.
  618.         ret     4
  619.  
  620. ; This subroutine is called by getattr and open.
  621. ; This subroutine looks for file name and returns NULL or pointer to file info record.
  622. lookup_file_name:
  623.         mov     ebp, [esp+8]    ; hPlugin
  624.         mov     esi, [esp+12]   ; filename
  625.         lea     edi, [ebp+handle_common.root.subfolders]
  626.         xor     eax, eax
  627. ; KFar operates with absolute names, skip first '/'
  628.         cmp     byte [esi], '/'
  629.         jnz     .notfound
  630.         inc     esi
  631. .mainloop:
  632. ; get next component of name
  633.         push    -1
  634.         pop     ecx
  635. @@:
  636.         inc     ecx
  637.         cmp     byte [esi+ecx], '/'
  638.         jz      @f
  639.         cmp     byte [esi+ecx], 0
  640.         jnz     @b
  641. @@:
  642. ; esi->component, ecx=length
  643. ; scan for required item in subfolders list
  644.         push    -1
  645.         mov     eax, [edi]      ; .subfolders
  646. .scan1:
  647.         test    eax, eax
  648.         jz      .notfound1
  649.         add     eax, ebp
  650.         cmp     [eax+file_common.namelen], ecx
  651.         jnz     .cont1
  652.         push    ecx esi edi
  653.         mov     edi, [eax+file_common.name]
  654.         repz    cmpsb
  655.         pop     edi esi ecx
  656.         jz      .found1
  657. .cont1:
  658.         mov     eax, [eax+file_common.next]
  659.         jmp     .scan1
  660. .notfound1:
  661.         pop     edx
  662. ; if this is last component in file name, scan in subfiles list
  663.         cmp     byte [esi+ecx], al
  664.         jnz     .notfound
  665.         inc     edx
  666.         jnz     .notfound
  667.         mov     eax, [edi+8]    ; .subfiles
  668.         push    edx
  669.         jmp     .scan1
  670. .found1:
  671.         pop     edi
  672. ; item is found, go to next component
  673.         lea     edi, [eax+file_common.subfolders]
  674.         lea     esi, [esi+ecx+1]
  675.         cmp     byte [esi-1], 0
  676.         jnz     .mainloop
  677. ; this was the last component
  678. .notfound:
  679.         ret
  680.  
  681. ; Memory streams handling.
  682. ; Archive handlers create memory stream for small files:
  683. ; size of which is not greater than (free RAM size)/4 and
  684. ; not greater than following constant...
  685. ;LIMIT_FOR_MEM_STREAM = 2*1024*1024
  686. ; ...if it is defined. Now the definition is commented:
  687. ; if user has many physical memory, why not to use it?
  688.  
  689. virtual at 0
  690. mem_stream:
  691. .type   dd      ?       ; type_mem_stream
  692. .size   dd      ?
  693. .pos    dd      ?
  694. .buf:
  695. end virtual
  696.  
  697. ; unsigned __stdcall read(ebx = HANDLE hFile, void* buf, unsigned size);
  698. read_mem_stream:
  699.         mov     eax, [esp+12]
  700.         mov     ecx, [ebx+mem_stream.size]
  701.         sub     ecx, [ebx+mem_stream.pos]
  702.         jnc     @f
  703.         xor     ecx, ecx
  704. @@:
  705.         cmp     eax, ecx
  706.         jb      @f
  707.         mov     eax, ecx
  708. @@:
  709.         mov     ecx, eax
  710.         lea     esi, [ebx+mem_stream.buf]
  711.         add     esi, [ebx+mem_stream.pos]
  712.         add     [ebx+mem_stream.pos], eax
  713.         mov     edi, [esp+8]
  714.         mov     edx, ecx
  715.         shr     ecx, 2
  716.         rep     movsd
  717.         mov     ecx, edx
  718.         and     ecx, 3
  719.         rep     movsb
  720.         ret     12
  721.  
  722. ; void __stdcall setpos(ebx = HANDLE hFile, __int64 pos);
  723. setpos_mem_stream:
  724.         mov     eax, [esp+8]
  725.         mov     [ebx+mem_stream.pos], eax
  726.         ret     12
  727.  
  728. ; void __stdcall close(ebx = HANDLE hFile);
  729. close_mem_stream:
  730.         mov     ecx, ebx
  731.         call    [pgfree]
  732.         ret     4
  733.  
  734. ; Allocate handle for file
  735. ; esi -> handle table, ecx = size of handle
  736. alloc_handle:
  737. ; Handle table is L2-list of allocated pages.
  738. ; Scan for free entry
  739.         mov     edx, esi
  740. @@:
  741.         mov     edx, [edx]
  742.         cmp     edx, esi
  743.         jz      .alloc_new
  744.         mov     eax, [edx+8]            ; head of L1-list of free entries
  745.         test    eax, eax                ; has free entry?
  746.         jz      @b
  747. ; we have found allocated page with free entry; allocate entry and return
  748.         inc     dword [edx+12]          ; number of busy entries
  749.         push    dword [eax]
  750.         pop     dword [edx+8]
  751. .ret:
  752.         ret
  753. .alloc_new:
  754. ; no free pages; get new page and initialize
  755.         push    ecx
  756.         mov     ecx, 0x1000
  757.         call    [pgalloc]
  758.         pop     ecx
  759.         test    eax, eax
  760.         jz      .ret
  761. ; insert new page to start of L2-list
  762.         mov     edx, [esi]
  763.         mov     [eax], edx
  764.         mov     [esi], eax
  765.         mov     [eax+4], esi
  766.         mov     [edx+4], eax
  767.         mov     dword [eax+12], 1       ; 1 allocated entry
  768. ; initialize list of free entries
  769.         lea     edx, [eax+16]
  770.         push    edx     ; save return value
  771.         add     edx, ecx
  772.         mov     [eax+8], edx
  773.         add     eax, 0x1000
  774. @@:
  775.         mov     esi, edx
  776.         add     edx, ecx
  777.         mov     [esi], edx
  778.         cmp     edx, eax
  779.         jb      @b
  780.         and     dword [esi], 0
  781.         pop     eax
  782.         ret
  783.  
  784. ; Free handle allocated in previous procedure
  785. ; esi = handle
  786. free_handle:
  787.         mov     ecx, esi
  788.         and     ecx, not 0xFFF  ; get page
  789. ; add entry to head of L1-list of free entries
  790.         mov     eax, [ecx+8]
  791.         mov     [esi], eax
  792.         mov     [ecx+8], esi
  793.         dec     dword [ecx+12]  ; decrement number of allocated entries
  794.         jnz     .ret
  795. ; delete page from common L2-list
  796.         mov     eax, [ecx]
  797.         mov     edx, [ecx+4]
  798.         mov     [eax+4], edx
  799.         mov     [edx], eax
  800. ; free page
  801.         call    [pgfree]
  802. .ret:
  803.         ret
  804.  
  805. ; Ask user to enter password.
  806. ; Out: ZF set <=> user pressed Esc
  807. ;      'password_ansi', 'password_unicode', 'password_size' filled
  808. query_password:
  809.         cmp     [bPasswordDefined], 0
  810.         jnz     .ret
  811.         mov     edi, password_data
  812.         mov     eax, password_maxlen
  813.         stosd           ; maximum length
  814.         xor     eax, eax
  815.         stosd           ; start of visible part
  816.         stosd           ; position of cursor
  817.         stosb           ; initial state: empty string
  818.         mov     eax, [cur_console_size]
  819.         mov     eax, [eax]      ; get current console width
  820.         sub     eax, 12
  821.         mov     edi, password_dlg
  822.         mov     [edi+password_dlg.width-password_dlg], eax
  823.         dec     eax
  824.         dec     eax
  825.         mov     [edi+password_dlg.width1-password_dlg], eax
  826.         mov     [edi+password_dlg.width2-password_dlg], eax
  827.         push    edi
  828.         call    [DialogBox]
  829.         inc     eax
  830.         jz      .ret
  831. ; convert ANSI-cp866 to UNICODE string; also calculate 'password_size'
  832.         mov     esi, password_ansi
  833.         mov     edi, password_unicode
  834.         or      [password_size], -1
  835. .cvt:
  836.         inc     [password_size]
  837.         lodsb
  838.         mov     ah, 0
  839. ; 0x00-0x7F - trivial map
  840.         cmp     al, 0x80
  841.         jb      .symb
  842. ; 0x80-0xAF -> 0x410-0x43F
  843.         cmp     al, 0xB0
  844.         jae     @f
  845.         add     ax, 0x410-0x80
  846.         jmp     .symb
  847. @@:
  848. ; 0xE0-0xEF -> 0x440-0x44F
  849.         cmp     al, 0xE0
  850.         jb      .unk
  851.         cmp     al, 0xF0
  852.         jae     @f
  853.         add     ax, 0x440-0xE0
  854.         jmp     .symb
  855. @@:
  856. ; 0xF0 -> 0x401
  857. ; 0xF1 -> 0x451
  858.         cmp     al, 'ð'
  859.         jz      .yo1
  860.         cmp     al, 'ñ'
  861.         jz      .yo2
  862. .unk:
  863.         mov     al, '_'
  864.         jmp     .symb
  865. .yo1:
  866.         mov     ax, 0x401
  867.         jmp     .symb
  868. .yo2:
  869.         mov     ax, 0x451
  870. .symb:
  871.         stosw
  872.         test    al, al
  873.         jnz     .cvt
  874.         inc     [bPasswordDefined]      ; clears ZF flag
  875. .ret:
  876.         ret
  877.  
  878. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  879. ;;;;;;;;;;;;;;;; Initialized data ;;;;;;;;;;;;;;;
  880. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  881.  
  882. ; export table
  883. align 4
  884. EXPORTS:
  885.         dd      aVersion,       1
  886.         dd      aPluginLoad,    plugin_load
  887.         dd      aOpenFilePlugin,OpenFilePlugin
  888.         dd      aClosePlugin,   ClosePlugin
  889.         dd      aReadFolder,    ReadFolder
  890.         dd      aSetFolder,     SetFolder
  891.         dd      aGetFiles,      GetFiles
  892.         dd      aGetOpenPluginInfo, GetOpenPluginInfo
  893.         dd      aGetattr,       mygetattr
  894.         dd      aOpen,          myopen
  895.         dd      aRead,          myread
  896.         dd      aSetpos,        mysetpos
  897.         dd      aClose,         myclose
  898.         dd      0
  899.  
  900. ; exported names
  901. aVersion        db      'version',0
  902. aPluginLoad     db      'plugin_load',0
  903. aOpenFilePlugin db      'OpenFilePlugin',0
  904. aClosePlugin    db      'ClosePlugin',0
  905. aReadFolder     db      'ReadFolder',0
  906. aSetFolder      db      'SetFolder',0
  907. aGetFiles       db      'GetFiles',0
  908. aGetOpenPluginInfo db   'GetOpenPluginInfo',0
  909. aGetattr        db      'getattr',0
  910. aOpen           db      'open',0
  911. aRead           db      'read',0
  912. aSetpos         db      'setpos',0
  913. aClose          db      'close',0
  914.  
  915. ; common strings
  916. if lang eq ru
  917. aContinue       db      'à®¤®«¦¨âì',0
  918. aCancel         db      'Žâ¬¥­ ',0
  919. aHeaderError    db      'Žè¨¡ª  ¢ § £®«®¢ª¥  à娢 ',0
  920. aReadError      db      'Žè¨¡ª  ç⥭¨ï',0
  921. aNoFreeRam      db      '¥¤®áâ â®ç­® ᢮¡®¤­®© ®¯¥à â¨¢­®© ¯ ¬ïâ¨',0
  922. aEncodingProblem db     'à®¡«¥¬  á ª®¤¨à®¢ª®©',0
  923. aEncodingProblem_str db 'ˆ¬¥­  ­¥ª®â®àëå ä ©«®¢ ¢  à娢¥ ᮤ¥à¦ â ᨬ¢®«ë,',0
  924. .2              db      '­¥ ¯à¥¤áâ ¢¨¬ë¥ ¢ ª®¤¨à®¢ª¥ cp866.',0
  925. .3              db      'â¨ ᨬ¢®«ë ¡ã¤ãâ § ¬¥­¥­ë ­  ¯®¤çñન¢ ­¨ï.',0
  926. aEnterPassword  db      '‚¢¥¤¨â¥ ¯ à®«ì:',0
  927. aEnterPasswordLen = $ - aEnterPassword - 1
  928. aEnterPasswordTitle db  '‚¢®¤ ¯ à®«ï',0
  929. aArchiveDataError db    'Žè¨¡ª  ¢ ¤ ­­ëå  à娢 ',0
  930. aArchiveDataErrorPass db 'Žè¨¡ª  ¢ ¤ ­­ëå  à娢  ¨«¨ ­¥¢¥à­ë© ¯ à®«ì',0
  931. aChangePass     db      '‚¢¥á⨠¯ à®«ì',0
  932. aNameTooLong    db      '‘«¨èª®¬ ¤«¨­­®¥ ¨¬ï',0
  933. else
  934. aContinue       db      'Continue',0
  935. aCancel         db      'Cancel',0
  936. aHeaderError    db      'Invalid archive header',0
  937. aReadError      db      'Read error',0
  938. aNoFreeRam      db      'There is not enough of free RAM',0
  939. aEncodingProblem db     'Encoding problem',0
  940. aEncodingProblem_str db 'The names of some files in the archive contain',0
  941. .2              db      'characters which can not be represented in cp866.',0
  942. .3              db      'Such characters will be replaced to underscores.',0
  943. aEnterPassword  db      'Enter password:',0
  944. aEnterPasswordLen = $ - aEnterPassword - 1
  945. aEnterPasswordTitle db  'Get password',0
  946. aArchiveDataError db    'Error in archive data',0
  947. aArchiveDataErrorPass db 'Error in archive data or incorrect password',0
  948. aChangePass     db      'Enter password',0
  949. aNameTooLong    db      'Name is too long',0
  950. end if
  951.  
  952. ; kfar_arc supports [hmm... will support...] many archive types.
  953. ; OpenFilePlugin looks for supported archive signature and gives control
  954. ;   to concrete handler if found.
  955. ; Other functions just determine type of opened archive and jumps to corresponding handler.
  956. type_mem_stream = 0     ; memory stream - for file handles (returned from 'open')
  957. type_7z = 1
  958.  
  959. ; archive functions (types start from type_7z)
  960. align 4
  961. ClosePluginTable:
  962.         dd      close_7z
  963. ReadFolderTable:
  964.         dd      ReadFolder_7z
  965. SetFolderTable:
  966.         dd      SetFolder_7z
  967. GetFilesTable:
  968.         dd      GetFiles_7z
  969. getattrTable:
  970.         dd      getattr_7z
  971. openTable:
  972.         dd      open_file_7z
  973.  
  974. ; file functions (types start from type_mem_stream)
  975. readTable:
  976.         dd      read_mem_stream
  977.         dd      read_7z
  978. setposTable:
  979.         dd      setpos_mem_stream
  980.         dd      setpos_7z
  981. closeTable:
  982.         dd      close_mem_stream
  983.         dd      close_file_7z
  984.  
  985. ; pointers for SayErr and Message
  986. ContinueBtn     dd      aContinue
  987. HeaderError_ptr dd      aHeaderError
  988. aReadError_ptr  dd      aReadError
  989. aNoFreeRam_ptr  dd      aNoFreeRam
  990. aEncodingProblem_str_ptr:
  991.                 dd      aEncodingProblem_str
  992.                 dd      aEncodingProblem_str.2
  993.                 dd      aEncodingProblem_str.3
  994. aNameTooLong_ptr dd     aNameTooLong
  995. aArchiveDataError_ptr dd aArchiveDataError
  996. aArchiveDataErrorPass_ptr dd aArchiveDataErrorPass
  997. CancelPassBtn   dd      aCancel
  998.                 dd      aChangePass
  999.  
  1000. ; "enter password" dialog for KFar
  1001. password_dlg:
  1002.         dd      1       ; use standard dialog colors
  1003.         dd      -1      ; center window by x
  1004.         dd      -1      ; center window by y
  1005. .width  dd      ?       ; width (will be filled according to current console width)
  1006.         dd      2       ; height
  1007.         dd      4, 2    ; border size
  1008.         dd      aEnterPasswordTitle     ; title
  1009.         dd      ?       ; colors (will be set by KFar)
  1010.         dd      0, 0    ; reserved for DlgProc
  1011.         dd      2       ; 2 controls
  1012. ; the string "enter password"
  1013.         dd      1       ; type: static
  1014.         dd      1,0     ; upper-left position
  1015. .width1 dd      ?,0     ; bottom-right position
  1016.         dd      aEnterPassword  ; data
  1017.         dd      0       ; flags
  1018. ; editbox for password
  1019.         dd      3       ; type: edit
  1020.         dd      1,1     ; upper-left position
  1021. .width2 dd      ?,0     ; bottom-right position
  1022.         dd      password_data   ; data
  1023.         dd      2Ch     ; flags
  1024.  
  1025. IncludeIGlobals
  1026.  
  1027. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1028. ;;;;;;;;;;;;;;; Uninitialized data ;;;;;;;;;;;;;;
  1029. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1030.  
  1031. section '.udata' data readable writable align 16
  1032. kfar_info       dd      ?
  1033. crc_table       rd      256
  1034. _esp            dd      ?
  1035. _ebp            dd      ?
  1036. bufsize         dd      ?
  1037. bufptr          dd      ?
  1038. bufend          dd      ?
  1039. buffer          rb      1024
  1040. inStream        dd      ?
  1041. hOut            dd      ?
  1042. .allocated      dd      ?
  1043.  
  1044. error_proc      dd      ?
  1045. clear_proc      dd      ?
  1046.  
  1047. ; import from kfar
  1048. read            dd      ?
  1049. seek            dd      ?
  1050. close           dd      ?
  1051. pgalloc         dd      ?
  1052. pgrealloc       dd      ?
  1053. pgfree          dd      ?
  1054. getfreemem      dd      ?
  1055. DialogBox       dd      ?
  1056. SayErr          dd      ?
  1057. Message         dd      ?
  1058. cur_console_size dd     ?
  1059.  
  1060. ; data for editbox in kfar dialog
  1061. password_maxlen = 512
  1062. password_data:
  1063. .maxlen         dd      ?
  1064. .pos            dd      ?
  1065. .start          dd      ?
  1066. password_ansi   rb      password_maxlen+1
  1067. bPasswordDefined db     ?
  1068.  
  1069. ; converted password
  1070. password_unicode rw     password_maxlen+1
  1071. password_size   dd      ?
  1072.  
  1073. IncludeUGlobals
  1074.  
  1075. bWasWarning     db      ?
  1076.