Subversion Repositories Kolibri OS

Rev

Rev 1148 | Details | Compare with Previous | 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
1148 diamond 5
; version:              0.17
6673 IgorA 6
; last update:          2016-11-04 (Nov 04, 2016)
926 diamond 7
; minimal KFar version: 0.43
589 diamond 8
; minimal kernel:       no limit
9
;
10
; author:               Diamond
11
; email:                diamondz@land.ru
1148 diamond 12
; web:                  http://diamond.kolibrios.org
589 diamond 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
6673 IgorA 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
589 diamond 27
; include main code for archives loading
6673 IgorA 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
589 diamond 36
 
37
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38
;;;;;;;;;;;;;;; Interface for KFar ;;;;;;;;;;;;;;
39
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40
virtual at 0
41
kfar_info_struc:
6673 IgorA 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	?
589 diamond 66
end virtual
67
 
68
; int __stdcall plugin_load(kfar_info* info);
69
; Initialization of plugin + Save used KFar functions.
70
plugin_load:
6673 IgorA 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
589 diamond 100
 
631 diamond 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);
589 diamond 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:
6673 IgorA 109
	mov	[bPasswordDefined], 0
110
	mov	esi, [esp+12]
111
	mov	ebp, [esp+4]
589 diamond 112
; test for 7z archive
6673 IgorA 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
589 diamond 121
.no_7z:
631 diamond 122
; test for zip archive
6673 IgorA 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
631 diamond 137
.zip:
6673 IgorA 138
	call	open_zip
139
	ret	28
631 diamond 140
.no_zip:
6673 IgorA 141
	xor	eax, eax
142
	ret	28
589 diamond 143
 
144
; Handle of plugin in kfar_arc is as follow:
145
virtual at 0
146
handle_common:
6673 IgorA 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	?
589 diamond 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:
6673 IgorA 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
589 diamond 176
end virtual
177
 
178
; void __stdcall ClosePlugin(HANDLE hPlugin);
179
; This function frees all resources allocated in OpenFilePlugin.
180
ClosePlugin:
6673 IgorA 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]
589 diamond 186
 
187
; int __stdcall ReadFolder(HANDLE hPlugin,
188
;       unsigned dirinfo_start, unsigned dirinfo_size, void* dirdata);
189
ReadFolder:
631 diamond 190
; init header
6673 IgorA 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]
631 diamond 197
; get current directory
6673 IgorA 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
631 diamond 203
@@:
6673 IgorA 204
	mov	ecx, [ebx+16]
205
	mov	[edi-24], ecx		; number of files
631 diamond 206
; edi points to BDFE
6673 IgorA 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
631 diamond 213
@@:
6673 IgorA 214
	cmp	ecx, [esp+12]
215
	jb	@f
216
	mov	ecx, [esp+12]
217
	xor	eax, eax	; OK
631 diamond 218
@@:
6673 IgorA 219
	mov	[edi-28], ecx
220
	push	eax
631 diamond 221
; copy files data
6673 IgorA 222
	jecxz	.done
631 diamond 223
; seek to required item
6673 IgorA 224
	mov	eax, [esp+8+4]
225
	mov	esi, [ebx]
631 diamond 226
.0:
6673 IgorA 227
	test	esi, esi
228
	jnz	.1
229
	mov	esi, [ebx+8]
631 diamond 230
.1:
6673 IgorA 231
	add	esi, ebp
232
	dec	eax
233
	js	.2
234
	mov	esi, [esi+file_common.next]
235
	jmp	.0
631 diamond 236
.2:
237
.copy:
6673 IgorA 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]
631 diamond 255
@@:
6673 IgorA 256
	add	esi, ebp
257
	loop	.copy
631 diamond 258
.done:
6673 IgorA 259
	pop	eax
260
	ret	10h
589 diamond 261
 
262
; bool __stdcall SetFolder(HANDLE hPlugin,
263
;       const char* relative_path, const char* absolute_path);
264
SetFolder:
6673 IgorA 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
631 diamond 271
@@:
6673 IgorA 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]
631 diamond 279
.scan:
6673 IgorA 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
631 diamond 290
.cont:
6673 IgorA 291
	mov	ebx, [ebx+file_common.next]
292
	jmp	.scan
631 diamond 293
.toparent:
6673 IgorA 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
631 diamond 300
@@:
301
.set:
6673 IgorA 302
	mov	[ebp+handle_common.curdir], ebx
303
	mov	al, 1
304
	ret	12
631 diamond 305
.err:
6673 IgorA 306
	xor	eax, eax
307
	ret	12
589 diamond 308
 
631 diamond 309
iglobal
310
cur_stamp dd 0
311
endg
312
 
313
uglobal
6673 IgorA 314
tmp_bdfe	rb	304
631 diamond 315
endg
316
 
589 diamond 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:
6673 IgorA 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]
631 diamond 330
.loop:
6673 IgorA 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
631 diamond 344
.incur:
6673 IgorA 345
	cmp	byte [esi], '/'
346
	jnz	@f
347
	inc	esi
631 diamond 348
@@:
6673 IgorA 349
	mov	ecx, [esp+12]	; NumItems
350
	mov	edx, [esp+16]	; items
351
	cmp	ecx, -1
352
	jz	.ok
631 diamond 353
.check:
6673 IgorA 354
	sub	ecx, 1
355
	js	.cont
356
	push	esi
357
	mov	edi, [edx]
358
	add	edi, 40
631 diamond 359
@@:
6673 IgorA 360
	lodsb
361
	scasb
362
	jnz	@f
363
	test	al, al
364
	jz	.ok2
365
	jmp	@b
631 diamond 366
@@:
6673 IgorA 367
	pop	esi
368
	cmp	al, '/'
369
	jnz	@f
370
	cmp	byte [edi-1], 0
371
	jz	.ok
631 diamond 372
@@:
6673 IgorA 373
	add	edx, 4
374
	jmp	.check
631 diamond 375
.ok2:
6673 IgorA 376
	pop	esi
631 diamond 377
.ok:
378
; add all parents directories if needed
379
.parloope:
6673 IgorA 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
631 diamond 386
.parloopi:
6673 IgorA 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
631 diamond 393
@@:
6673 IgorA 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
631 diamond 417
.pardone:
6673 IgorA 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
631 diamond 444
.addfile:
6673 IgorA 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
631 diamond 473
.cont:
6673 IgorA 474
	mov	eax, [ebp]
475
	add	ebx, [basesizes+(eax-1)*8+4]
476
	pop	ecx
477
	dec	ecx
478
	jnz	.loop
631 diamond 479
.ret:
6673 IgorA 480
	ret	20
631 diamond 481
.forced_exit:
6673 IgorA 482
	pop	ecx
483
	jmp	.ret
589 diamond 484
 
485
; void __stdcall GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo* info);
486
GetOpenPluginInfo:
6673 IgorA 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
589 diamond 491
 
492
; int __stdcall getattr(HANDLE hPlugin, const char* filename, void* info);
493
mygetattr:
6673 IgorA 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
589 diamond 503
@@:
6673 IgorA 504
	mov	al, 5	; ERROR_FILE_NOT_FOUND
505
	ret	12
589 diamond 506
 
507
; HANDLE __stdcall open(HANDLE hPlugin, const char* filename, int mode);
508
myopen:
6673 IgorA 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]
589 diamond 516
@@:
6673 IgorA 517
	ret	12
589 diamond 518
 
519
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
520
myread:
6673 IgorA 521
	mov	ebx, [esp+4]
522
	mov	eax, [ebx]
523
	jmp	dword [readTable+eax*4]
589 diamond 524
 
525
; void __stdcall setpos(HANDLE hFile, __int64 pos);
526
mysetpos:
6673 IgorA 527
	mov	ebx, [esp+4]
528
	mov	eax, [ebx]
529
	jmp	dword [setposTable+eax*4]
589 diamond 530
 
531
; void __stdcall close(HANDLE hFile);
532
myclose:
6673 IgorA 533
	mov	ebx, [esp+4]
534
	mov	eax, [ebx]
535
	jmp	dword [closeTable+eax*4]
589 diamond 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:
6673 IgorA 544
	mov	esp, [_esp]
545
	mov	ebp, [_ebp]
546
	jmp	[error_proc]
589 diamond 547
return.clear:
6673 IgorA 548
	mov	esp, [_esp]
549
	mov	ebp, [_ebp]
550
	jmp	[clear_proc]
589 diamond 551
 
552
; data for following routine
553
iglobal
554
align 4
6673 IgorA 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
589 diamond 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
6673 IgorA 571
	push	eax
572
	mov	eax, edx
573
	xor	edx, edx
574
	div	[_10000000]
575
	xchg	eax, [esp]
576
	div	[_10000000]
577
	pop	edx
589 diamond 578
; edx:eax = number of seconds since January 1, 1601
6673 IgorA 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
589 diamond 587
; edx:eax = number of minutes
6673 IgorA 588
	div	[_60]
589
	mov	[edi+1], dl
589 diamond 590
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
6673 IgorA 591
	xor	edx, edx
592
	div	[_24]
593
	mov	[edi+2], dl
594
	mov	[edi+3], byte 0
589 diamond 595
; eax = number of days since January 1, 1601
6673 IgorA 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]
589 diamond 608
@@:
6673 IgorA 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]
589 diamond 623
@@:
6673 IgorA 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
589 diamond 640
.leap:
6673 IgorA 641
	mov	esi, months2
589 diamond 642
.noleap:
6673 IgorA 643
	pop	edx
644
	xor	eax, eax
645
	inc	eax
589 diamond 646
@@:
6673 IgorA 647
	sub	edx, [esi]
648
	jb	@f
649
	add	esi, 4
650
	inc	eax
651
	jmp	@b
589 diamond 652
@@:
6673 IgorA 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
589 diamond 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}
6673 IgorA 669
	xor	eax, eax
670
	mov	[.free], eax
671
	push	edi
672
	stosd
673
	stosd
674
	stosd
675
	stosd
676
	stosd
677
	pop	edi
589 diamond 678
; Loop through all files
679
.mainloop:
6673 IgorA 680
	dec	ebx
681
	js	.mainloopdone
589 diamond 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}
6673 IgorA 687
	mov	esi, [edx+file_common.fullname]
688
	mov	ecx, edi
589 diamond 689
.parseloop:
6673 IgorA 690
	push	esi
589 diamond 691
.parsename:
6673 IgorA 692
	lodsb
693
	test	al, al
694
	jz	@f
695
	cmp	al, '/'
696
	jnz	.parsename
589 diamond 697
@@:
698
; we have found next component of current name; look for it in current directory
6673 IgorA 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
589 diamond 709
@@:
6673 IgorA 710
	push	ecx
711
	mov	eax, [ecx]	; eax->subfolders list
712
	mov	ecx, esi
589 diamond 713
.scansubfolders:
6673 IgorA 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
589 diamond 725
.scancont:
6673 IgorA 726
	mov	eax, [eax+file_common.next]
727
	jmp	.scansubfolders
589 diamond 728
.subfound:
729
; found subfolder, set it as current and continue parsing name
6673 IgorA 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
589 diamond 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
6673 IgorA 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
589 diamond 746
; replace item in L2-list
6673 IgorA 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
589 diamond 755
.1:
6673 IgorA 756
	add	eax, [hOut]
589 diamond 757
.2:
6673 IgorA 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
589 diamond 767
.3:
6673 IgorA 768
	add	eax, [hOut]
589 diamond 769
.4:
6673 IgorA 770
	mov	[eax+file_common.prev], edx
589 diamond 771
; correct parent links in childrens
6673 IgorA 772
	mov	eax, [ecx]
589 diamond 773
@@:
6673 IgorA 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
589 diamond 780
@@:
6673 IgorA 781
	mov	eax, [ecx+8]
589 diamond 782
@@:
6673 IgorA 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
589 diamond 789
@@:
6673 IgorA 790
	add	edx, [hOut]
589 diamond 791
; set children links
6673 IgorA 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
589 diamond 802
; set prev/next links
6673 IgorA 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
589 diamond 807
; add old item to list of free items
808
uglobal
809
align 4
6673 IgorA 810
init_file_links.free	dd	?
589 diamond 811
endg
6673 IgorA 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
589 diamond 818
.nofolder:
6673 IgorA 819
	mov	eax, edx
820
	mov	esi, [esp+4]
821
	cmp	byte [esi+ecx], 0
822
	jz	.newitem
589 diamond 823
; the current item is as 'dir1/item1' and 'dir1' has not been found
824
; allocate virtual subfolder 'dir1'
6673 IgorA 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
589 diamond 832
.realloc:
833
; there is no free space, so reallocate [hOut] block
6673 IgorA 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
589 diamond 858
@@:
6673 IgorA 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]
589 diamond 866
.allocated:
867
; eax -> new item
6673 IgorA 868
	mov	[eax+file_common.bIsDirectory], 1
869
	mov	[eax+file_common.bPseudoFolder], 1
589 diamond 870
.newitem:
6673 IgorA 871
	mov	[eax+file_common.namelen], ecx
644 diamond 872
; !!! in this case .fullname is not null-terminated !!!
6673 IgorA 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
589 diamond 884
; ecx = parent item, eax = current item
6673 IgorA 885
	mov	[eax+file_common.name], esi
886
	inc	dword [ecx+16]	; new item in parent folder
887
	push	ecx
589 diamond 888
; add new item to end of L2-list
6673 IgorA 889
	cmp	[eax+file_common.bIsDirectory], 0
890
	jnz	@f
891
	add	ecx, 8
589 diamond 892
@@:
6673 IgorA 893
	push	eax
894
	sub	eax, [hOut]
895
	cmp	dword [ecx], 0
896
	jnz	@f
897
	mov	[ecx], eax
589 diamond 898
@@:
6673 IgorA 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]
589 diamond 908
@@:
6673 IgorA 909
	pop	ecx
589 diamond 910
; set parent link
6673 IgorA 911
	cmp	ecx, edi
912
	jz	@f
913
	sub	ecx, file_common.subfolders
914
	sub	ecx, [hOut]
915
	mov	[eax+file_common.parent], ecx
589 diamond 916
@@:
917
; set current directory to current item
6673 IgorA 918
	lea	ecx, [eax+file_common.subfolders]
589 diamond 919
; if that was not last component, continue parse name
6673 IgorA 920
	add	esi, [eax+file_common.namelen]
921
	lodsb
922
	test	al, al
923
	jnz	.parseloop
589 diamond 924
.mainloopcont:
925
; continue main loop
6673 IgorA 926
	add	edx, [esp+4]
927
	jmp	.mainloop
589 diamond 928
.mainloopdone:
929
; Loop done.
6673 IgorA 930
	ret	4
589 diamond 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:
6673 IgorA 935
	mov	ebp, [esp+8]	; hPlugin
936
	mov	esi, [esp+12]	; filename
937
	lea	edi, [ebp+handle_common.root.subfolders]
938
	xor	eax, eax
589 diamond 939
; KFar operates with absolute names, skip first '/'
6673 IgorA 940
	cmp	byte [esi], '/'
941
	jnz	.notfound
942
	inc	esi
589 diamond 943
.mainloop:
944
; get next component of name
6673 IgorA 945
	push	-1
946
	pop	ecx
589 diamond 947
@@:
6673 IgorA 948
	inc	ecx
949
	cmp	byte [esi+ecx], '/'
950
	jz	@f
951
	cmp	byte [esi+ecx], 0
952
	jnz	@b
589 diamond 953
@@:
954
; esi->component, ecx=length
955
; scan for required item in subfolders list
6673 IgorA 956
	push	-1
957
	mov	eax, [edi]	; .subfolders
589 diamond 958
.scan1:
6673 IgorA 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
589 diamond 969
.cont1:
6673 IgorA 970
	mov	eax, [eax+file_common.next]
971
	jmp	.scan1
589 diamond 972
.notfound1:
6673 IgorA 973
	pop	edx
589 diamond 974
; if this is last component in file name, scan in subfiles list
6673 IgorA 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
589 diamond 982
.found1:
6673 IgorA 983
	pop	edi
589 diamond 984
; item is found, go to next component
6673 IgorA 985
	lea	edi, [eax+file_common.subfolders]
986
	lea	esi, [esi+ecx+1]
987
	cmp	byte [esi-1], 0
988
	jnz	.mainloop
589 diamond 989
; this was the last component
990
.notfound:
6673 IgorA 991
	ret
589 diamond 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:
6673 IgorA 1003
.type	dd	?	; type_mem_stream
1004
.size	dd	?
1005
.pos	dd	?
589 diamond 1006
.buf:
1007
end virtual
1008
 
1009
; unsigned __stdcall read(ebx = HANDLE hFile, void* buf, unsigned size);
1010
read_mem_stream:
6673 IgorA 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
589 diamond 1016
@@:
6673 IgorA 1017
	cmp	eax, ecx
1018
	jb	@f
1019
	mov	eax, ecx
589 diamond 1020
@@:
6673 IgorA 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
589 diamond 1033
 
1034
; void __stdcall setpos(ebx = HANDLE hFile, __int64 pos);
1035
setpos_mem_stream:
6673 IgorA 1036
	mov	eax, [esp+8]
1037
	mov	[ebx+mem_stream.pos], eax
1038
	ret	12
589 diamond 1039
 
1040
; void __stdcall close(ebx = HANDLE hFile);
1041
close_mem_stream:
6673 IgorA 1042
	mov	ecx, ebx
1043
	call	[pgfree]
1044
	ret	4
589 diamond 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
6673 IgorA 1051
	mov	edx, esi
589 diamond 1052
@@:
6673 IgorA 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
589 diamond 1059
; we have found allocated page with free entry; allocate entry and return
6673 IgorA 1060
	inc	dword [edx+12]		; number of busy entries
1061
	push	dword [eax]
1062
	pop	dword [edx+8]
589 diamond 1063
.ret:
6673 IgorA 1064
	ret
589 diamond 1065
.alloc_new:
1066
; no free pages; get new page and initialize
6673 IgorA 1067
	push	ecx
1068
	mov	ecx, 0x1000
1069
	call	[pgalloc]
1070
	pop	ecx
1071
	test	eax, eax
1072
	jz	.ret
589 diamond 1073
; insert new page to start of L2-list
6673 IgorA 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
589 diamond 1080
; initialize list of free entries
6673 IgorA 1081
	lea	edx, [eax+16]
1082
	push	edx	; save return value
1083
	add	edx, ecx
1084
	mov	[eax+8], edx
1085
	add	eax, 0x1000
589 diamond 1086
@@:
6673 IgorA 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
589 diamond 1095
 
1096
; Free handle allocated in previous procedure
1097
; esi = handle
1098
free_handle:
6673 IgorA 1099
	mov	ecx, esi
1100
	and	ecx, not 0xFFF	; get page
589 diamond 1101
; add entry to head of L1-list of free entries
6673 IgorA 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
589 diamond 1107
; delete page from common L2-list
6673 IgorA 1108
	mov	eax, [ecx]
1109
	mov	edx, [ecx+4]
1110
	mov	[eax+4], edx
1111
	mov	[edx], eax
589 diamond 1112
; free page
6673 IgorA 1113
	call	[pgfree]
589 diamond 1114
.ret:
6673 IgorA 1115
	ret
589 diamond 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:
6673 IgorA 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
589 diamond 1143
; convert ANSI-cp866 to UNICODE string; also calculate 'password_size'
6673 IgorA 1144
	mov	esi, password_ansi
1145
	mov	edi, password_unicode
1146
	or	[password_size], -1
589 diamond 1147
.cvt:
6673 IgorA 1148
	inc	[password_size]
1149
	lodsb
1150
	mov	ah, 0
589 diamond 1151
; 0x00-0x7F - trivial map
6673 IgorA 1152
	cmp	al, 0x80
1153
	jb	.symb
589 diamond 1154
; 0x80-0xAF -> 0x410-0x43F
6673 IgorA 1155
	cmp	al, 0xB0
1156
	jae	@f
1157
	add	ax, 0x410-0x80
1158
	jmp	.symb
589 diamond 1159
@@:
1160
; 0xE0-0xEF -> 0x440-0x44F
6673 IgorA 1161
	cmp	al, 0xE0
1162
	jb	.unk
1163
	cmp	al, 0xF0
1164
	jae	@f
1165
	add	ax, 0x440-0xE0
1166
	jmp	.symb
589 diamond 1167
@@:
1168
; 0xF0 -> 0x401
1169
; 0xF1 -> 0x451
6673 IgorA 1170
	cmp	al, 'Ё'
1171
	jz	.yo1
1172
	cmp	al, 'ё'
1173
	jz	.yo2
589 diamond 1174
.unk:
6673 IgorA 1175
	mov	al, '_'
1176
	jmp	.symb
589 diamond 1177
.yo1:
6673 IgorA 1178
	mov	ax, 0x401
1179
	jmp	.symb
589 diamond 1180
.yo2:
6673 IgorA 1181
	mov	ax, 0x451
589 diamond 1182
.symb:
6673 IgorA 1183
	stosw
1184
	test	al, al
1185
	jnz	.cvt
1186
	inc	[bPasswordDefined]	; clears ZF flag
589 diamond 1187
.ret:
6673 IgorA 1188
	ret
589 diamond 1189
 
1190
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1022 diamond 1191
;;;;;;;;;;;;; API for other programs ;;;;;;;;;;;;
1192
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1193
; void* __stdcall deflate_unpack(void* packed_data, unsigned* pLength)
1194
deflate_unpack:
1195
	push	dword [esp+8]
6673 IgorA 1196
	push	esp
1197
	push	deflate_unpack_cb
1198
	call	deflate_unpack2
1199
	ret	8
1022 diamond 1200
 
1201
deflate_unpack_cb:
6673 IgorA 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
1022 diamond 1212
 
1213
; void* __stdcall deflate_unpack2(void* get_next_chunk, void* parameter, unsigned* pUnpackedLength)
6673 IgorA 1214
;       void* __stdcall get_next_chunk(void* parameter, unsigned* pLength)
1022 diamond 1215
deflate_unpack2:
6673 IgorA 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
1022 diamond 1237
.loop:
6673 IgorA 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]
1022 diamond 1245
@@:
6673 IgorA 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
1022 diamond 1265
.error:
6673 IgorA 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
1022 diamond 1279
@@:
6673 IgorA 1280
	test	ecx, ecx
1281
	jnz	@f
1282
	inc	ecx
1022 diamond 1283
@@:
6673 IgorA 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
1022 diamond 1309
.nomem:
6673 IgorA 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
1022 diamond 1320
@@:
6673 IgorA 1321
	lea	ecx, [ebp-streamInfo.size-8]
1322
	int	0x40
1323
	xor	eax, eax
1022 diamond 1324
.ret:
6673 IgorA 1325
	mov	[esp+28], eax
1326
	popa
1327
	ret	12
1022 diamond 1328
.fillBuf:
6673 IgorA 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
1022 diamond 1341
@@:
6673 IgorA 1342
	popad
1343
	ret
1022 diamond 1344
 
1345
mypgalloc:
6673 IgorA 1346
	push	SF_SYS_MISC
1347
	pop	eax
1348
	push	SSF_MEM_ALLOC
1349
	pop	ebx
1350
	int	0x40
1351
	ret
1022 diamond 1352
 
1353
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
589 diamond 1354
;;;;;;;;;;;;;;;; Initialized data ;;;;;;;;;;;;;;;
1355
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1356
 
1357
; export table
1358
align 4
1359
EXPORTS:
6673 IgorA 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
589 diamond 1383
 
1384
; exported names
6673 IgorA 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
589 diamond 1407
 
1408
; common strings
1409
if lang eq ru
6673 IgorA 1410
aContinue	db	'Продолжить',0
1411
aCancel 	db	'Отмена',0
1412
aHeaderError	db	'Ошибка в заголовке архива',0
1413
aReadError	db	'Ошибка чтения',0
1414
aNoFreeRam	db	'Недостаточно свободной оперативной памяти',0
1415
aEncodingProblem db	'Проблема с кодировкой',0
589 diamond 1416
aEncodingProblem_str db 'Имена некоторых файлов в архиве содержат символы,',0
6673 IgorA 1417
.2		db	'не представимые в кодировке cp866.',0
1418
.3		db	'Эти символы будут заменены на подчёркивания.',0
1419
aEnterPassword	db	'Введите пароль:',0
589 diamond 1420
aEnterPasswordLen = $ - aEnterPassword - 1
6673 IgorA 1421
aEnterPasswordTitle db	'Ввод пароля',0
1422
aArchiveDataError db	'Ошибка в данных архива',0
589 diamond 1423
aArchiveDataErrorPass db 'Ошибка в данных архива или неверный пароль',0
6673 IgorA 1424
aChangePass	db	'Ввести пароль',0
1425
aNameTooLong	db	'Слишком длинное имя',0
1426
aCannotOpenFile db	'Не могу открыть файл',0
589 diamond 1427
else
6673 IgorA 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
589 diamond 1434
aEncodingProblem_str db 'The names of some files in the archive contain',0
6673 IgorA 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
589 diamond 1438
aEnterPasswordLen = $ - aEnterPassword - 1
6673 IgorA 1439
aEnterPasswordTitle db	'Get password',0
1440
aArchiveDataError db	'Error in archive data',0
589 diamond 1441
aArchiveDataErrorPass db 'Error in archive data or incorrect password',0
6673 IgorA 1442
aChangePass	db	'Enter password',0
1443
aNameTooLong	db	'Name is too long',0
1444
aCannotOpenFile db	'Cannot open file',0
589 diamond 1445
end if
1446
 
631 diamond 1447
; kfar_arc supports many archive types.
589 diamond 1448
; OpenFilePlugin looks for supported archive signature and gives control
1449
;   to concrete handler if found.
631 diamond 1450
; Other functions just determine type of opened archive and jump to corresponding handler.
6673 IgorA 1451
type_mem_stream = 0	; memory stream - for file handles (returned from 'open')
589 diamond 1452
type_7z = 1
631 diamond 1453
type_zip = 2
589 diamond 1454
 
1455
; archive functions (types start from type_7z)
1456
align 4
1457
ClosePluginTable:
6673 IgorA 1458
	dd	close_7z
1459
	dd	close_zip
589 diamond 1460
getattrTable:
6673 IgorA 1461
	dd	getattr_7z
1462
	dd	getattr_zip
589 diamond 1463
openTable:
6673 IgorA 1464
	dd	open_file_7z
1465
	dd	open_file_zip
631 diamond 1466
basesizes:
6673 IgorA 1467
	dd	handle_7z.basesize, file_in_7z.size
1468
	dd	handle_zip.basesize, file_in_zip.size
589 diamond 1469
 
1470
; file functions (types start from type_mem_stream)
1471
readTable:
6673 IgorA 1472
	dd	read_mem_stream
1473
	dd	read_7z
1474
	dd	read_zip
589 diamond 1475
setposTable:
6673 IgorA 1476
	dd	setpos_mem_stream
1477
	dd	setpos_7z
1478
	dd	setpos_zip
589 diamond 1479
closeTable:
6673 IgorA 1480
	dd	close_mem_stream
1481
	dd	close_file_7z
1482
	dd	close_file_zip
589 diamond 1483
 
1484
; pointers for SayErr and Message
6673 IgorA 1485
ContinueBtn	dd	aContinue
1486
HeaderError_ptr dd	aHeaderError
1487
aReadError_ptr	dd	aReadError
1488
aNoFreeRam_ptr	dd	aNoFreeRam
589 diamond 1489
aEncodingProblem_str_ptr:
6673 IgorA 1490
		dd	aEncodingProblem_str
1491
		dd	aEncodingProblem_str.2
1492
		dd	aEncodingProblem_str.3
1493
aNameTooLong_ptr dd	aNameTooLong
589 diamond 1494
aArchiveDataError_ptr dd aArchiveDataError
1495
aArchiveDataErrorPass_ptr dd aArchiveDataErrorPass
6673 IgorA 1496
CancelPassBtn	dd	aCancel
1497
		dd	aChangePass
589 diamond 1498
 
1499
; "enter password" dialog for KFar
1500
password_dlg:
6673 IgorA 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
589 diamond 1512
; the string "enter password"
6673 IgorA 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
589 diamond 1518
; editbox for password
6673 IgorA 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
589 diamond 1524
 
1525
IncludeIGlobals
1526
 
1527
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1528
;;;;;;;;;;;;;;; Uninitialized data ;;;;;;;;;;;;;;
1529
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6673 IgorA 1530
purge data	;used in 'macros.inc'
1531
purge section	;used in 'macros.inc'
589 diamond 1532
 
1533
section '.udata' data readable writable align 16
6673 IgorA 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	?
589 diamond 1545
 
6673 IgorA 1546
error_proc	dd	?
1547
clear_proc	dd	?
589 diamond 1548
 
1549
; import from kfar
6673 IgorA 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	?
589 diamond 1563
 
1564
; data for editbox in kfar dialog
1565
password_maxlen = 512
1566
password_data:
6673 IgorA 1567
.maxlen 	dd	?
1568
.pos		dd	?
1569
.start		dd	?
1570
password_ansi	rb	password_maxlen+1
1571
bPasswordDefined db	?
589 diamond 1572
 
1573
; converted password
6673 IgorA 1574
password_unicode rw	password_maxlen+1
1575
password_size	dd	?
589 diamond 1576
 
1577
IncludeUGlobals
1578
 
6673 IgorA 1579
bWasWarning	db	?