Subversion Repositories Kolibri OS

Rev

Rev 631 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
589 diamond 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      ?