Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 529 → Rev 589

/programs/fs/kfar/trunk/api.txt
0,0 → 1,137
« £¨­ ¯à¥¤áâ ¢«ï¥â ᮡ®© áâ ­¤ àâ­ãî ¤«ï Š®«¨¡à¨ ¤¨­ ¬¨ç¥áªãî ¡¨¡«¨®â¥ªã (ä®à¬ â  COFF),
íªá¯®àâ¨àãîéãî á«¥¤ãî騥 ä㭪樨 ¨ ¯¥à¥¬¥­­ë¥ (­¥ª®â®àë¥ ä㭪樨 ¬®£ãâ ®âáãâá⢮¢ âì).
”㭪樨 ¬®£ãâ à §àãè âì «î¡ë¥ ॣ¨áâàë. kfar £ à ­â¨àã¥â á¡à®è¥­­ë© ä« £ ­ ¯à ¢«¥­¨ï DF
¯à¨ ¢ë§®¢¥ íªá¯®àâ¨à㥬ëå ä㭪権 ¨ ®¦¨¤ ¥â ⮣® ¦¥ ¤«ï callback-ä㭪権.
 
int version;
‚¥àá¨ï ¨­â¥àä¥©á  kfar, ­  ª®â®àãî à ááç¨â ­ ¯« £¨­. ‘¥©ç á ¤®«¦­  ¡ëâì 1.
 
int __stdcall plugin_load(kfar_info* info);
‚ë§ë¢ ¥âáï ¯à¨ § £à㧪¥ ¯« £¨­ .
typedef struct
{
int StructSize; // = sizeof(kfar_info)
int kfar_ver; // 10000h*major + minor
/* ‚ᥠcallback-ä㭪樨 á®åà ­ïî⠢ᥠॣ¨áâàë, §  ¨áª«î祭¨¥¬ eax. */
/* ”㭪樨 à ¡®âë á ä ©« ¬¨: */
void* open; // HANDLE __stdcall open(const char* name, int mode);
// mode - ª®¬¡¨­ æ¨ï ¡¨â®¢ëå ä« £®¢
// O_READ = 1 - ¤®áâ㯠¤«ï ç⥭¨ï
// O_WRITE = 2 - ¤®áâ㯠¤«ï § ¯¨á¨
// O_CREATE = 4 - ¥á«¨ ä ©« ­¥ áãé¥áâ¢ã¥â, ᮧ¤ âì ¥£®
// O_TRUNCATE = 8 - ãá¥çì ä ©« ¤® ­ã«¥¢®© ¤«¨­ë
void* read; // unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
void* write; // ¥éñ ­¥ ॠ«¨§®¢ ­®
void* seek; // void __stdcall seek(HANDLE hFile, int method, __int64 newpos);
void* flush; // ¥éñ ­¥ ॠ«¨§®¢ ­®
void* filesize; // __int64 __stdcall filesize(HANDLE hFile);
void* close; // void __stdcall close(HANDLE hFile);
/* ”㭪樨 à ¡®âë á ¯ ¬ïâìî (¯®áâà ­¨ç­®): */
void* pgalloc; // in: ecx=size, out: eax=pointer or NULL
// ¯à¨ ­¥å¢ âª¥ ¯ ¬ï⨠ᮮ¡é ¥â ¯®«ì§®¢ â¥«î ¨ ¢®§¢à é ¥â NULL
void* pgrealloc; // in: edx=pointer, ecx=new size, out: eax=pointer or NULL
// ¯à¨ ­¥å¢ âª¥ ¯ ¬ï⨠ᮮ¡é ¥â ¯®«ì§®¢ â¥«î ¨ ¢®§¢à é ¥â NULL
void* pgfree; // in: ecx=pointer
void* getfreemem; // unsigned __stdcall getfreemem(void);
// ¢®§¢à é ¥â à §¬¥à ᢮¡®¤­®© ®¯¥à â¨¢­®© ¯ ¬ï⨠¢ Š¡
void* pgalloc2; // void* __stdcall pgalloc2(unsigned size);
void* pgrealloc2; // void* __stdcall pgrealloc2(void* pointer, unsigned size);
void* pgfree2; // void __stdcall pgfree2(void* pointer);
/* ”㭪樨 à ¡®âë á ¤¨ «®£ ¬¨: */
void* menu; // int __stdcall menu(void* variants, const char* title, unsigned flags);
// variants 㪠§ë¢ ¥â ­  ⥪ã騩 í«¥¬¥­â ¢ ¤¢ãá¢ï§­®¬ ᯨ᪥
void* menu_centered_in; // int __stdcall menu_centered_in(unsigned left, unsigned top,
// unsigned width, unsigned height,
// void* variants, const char* title, unsigned flags);
void* DialogBox; // int __stdcall DialogBox(DLGDATA* dlg);
void* SayErr; // int __stdcall SayErr(int num_strings, const char** strings,
// int num_buttons, const char** buttons);
void* Message; // int __stdcall Message(const char* title,
// int num_strings, const char** strings,
// int num_buttons, const char** buttons);
// may be x=-1 and/or y=-1
struct {unsigned width;unsigned height;}* cur_console_size;
} kfar_info;
‚®§¢à é ¥¬®¥ §­ ç¥­¨¥:
0 = ãá¯¥è­ ï ¨­¨æ¨ «¨§ æ¨ï
1 = ®è¨¡ª  ¨­¨æ¨ «¨§ æ¨¨ (kfar ¢ë¤ áâ á®®¡é¥­¨¥ ¯®«ì§®¢ â¥«î)
2 = ®è¨¡ª  ¨­¨æ¨ «¨§ æ¨¨ (kfar ¯à®¤®«¦¨â ¡¥§ á®®¡é¥­¨©)
 
void __stdcall plugin_unload(void);
‚ë§ë¢ ¥âáï ¯à¨ ¢ë£à㧪¥ ¯« £¨­  (¢ ¯à®æ¥áᥠ§ ¢¥à襭¨ï à ¡®âë kfar).
 
HANDLE __stdcall OpenFilePlugin(HANDLE basefile, const char* name,
const void* attr, const void* data, int datasize);
Žâªà뢠¥â ¯« £¨­, í¬ã«¨àãî騩 ä ©«®¢ãî á¨á⥬㠭  ¡ §¥ ä ©«  (­ ¯à¨¬¥à,  à娢 ).
basefile - åí­¤« ä ©«  (ª ª®â®à®¬ã ¯à¨¬¥­¨¬ë ä㭪樨 read ¨ seek ¨§ kfar_info)
name - ¨¬ï ä ©«  (¢® ¢à¥¬¥­­®¬ ¡ãä¥à¥)
attr - 㪠§ â¥«ì ­  áâàãªâãàã á  âਡãâ ¬¨ ä ©«  ¢ ä®à¬ â¥ á¨á⥬­®© ä㭪樨 70.1
data - ¡ãä¥à, ᮤ¥à¦ é¨© ¤ ­­ë¥ ¨§ ­ ç «  ä ©«  (¬®¦¥â ¨á¯®«ì§®¢ âìáï ¤«ï ®¯à¥¤¥«¥­¨ï ⨯  ä ©« )
datasize - à §¬¥à ¤ ­­ëå ¢ data. ‚ ⥪ã饩 ॠ«¨§ æ¨¨ min(1024,à §¬¥à ä ©« )
…᫨ ¯« £¨­ ®¡à ¡ â뢠¥â ¯¥à¥¤ ­­ë© ä ©«, â® ®­ ¤®«¦¥­ ¢¥à­ãâì ­®¢ë© ®¯¨á â¥«ì,
ª®â®àë© ¢ ¤ «ì­¥©è¥¬ ¡ã¤¥â ¨á¯®«ì§®¢ âì kfar ¤«ï ®¡à é¥­¨ï ª ¯« £¨­ã. ‚ í⮬ á«ãç ¥
¯« £¨­ ¤®«¦¥­ á ¬®áâ®ï⥫쭮 § ªàëâì basefile ä㭪樥© close ¨§ kfar_info (­ ¯à¨¬¥à,
¯à¨ § ªàë⨨ ®¯¨á â¥«ï ¯« £¨­  ¢ ClosePlugin ¨«¨ ­¥¯®á।á⢥­­® ¢ OpenFilePlugin,
¥á«¨ basefile ¢®®¡é¥ ¢¯®á«¥¤á⢨¨ ­¥ ­ã¦¥­).
…᫨ ¯« £¨­ ­¥ ®¡à ¡ â뢠¥â ¯¥à¥¤ ­­ë© ä ©«, ¤®«¦¥­ ¢®§¢à é âìáï 0.
…᫨ ®¯¥à æ¨ï ¯à¥à¢ ­  ¯®«ì§®¢ â¥«¥¬, ¤®«¦­® ¢®§¢à é âìáï §­ ç¥­¨¥ -1.
 
void __stdcall ClosePlugin(HANDLE hPlugin);
‡ ªà뢠¥â ᮧ¤ ­­ë© ¢ OpenFilePlugin ®¯¨á â¥«ì.
 
void __stdcall GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo* Info);
®«ãç¨âì ¨­ä®à¬ æ¨î ®¡ ®âªàë⮬ íª§¥¬¯«ïॠ¯« £¨­ .
typedef struct
{
unsigned flags; // ¡¨â 0: ¤®¡ ¢«ïâì í«¥¬¥­â '..', ¥á«¨ ®­ ®âáãâáâ¢ã¥â
// ¡¨â 1: ª®¯¨à®¢ ­¨¥ ®¡à ¡ â뢠¥âáï ä㭪樥© GetFiles
} OpenPluginInfo;
 
void __stdcall GetPanelTitle(HANDLE hPlugin, char title[1024],
const char* host_file, const char* curdir);
®«ãç¨âì § £®«®¢®ª ¯ ­¥«¨ ¯« £¨­ .  à ¬¥âà host_file ᮢ¯ ¤ ¥â á ¨¬¥­¥¬ ä ©« , ¯¥à¥¤ ­­ë¬
¢ OpenFilePlugin.  à ¬¥âà curdir ᮢ¯ ¤ ¥â á ⥪ã饩 ¯ ¯ª®©, ãáâ ­ ¢«¨¢ ¥¬®© ¢ SetFolder.
 
int __stdcall ReadFolder(HANDLE hPlugin, unsigned dirinfo_start,
unsigned dirinfo_size, void* dirdata);
—¨â ¥â ⥪ãéãî ¯ ¯ªã. hPlugin - ¢®§¢à éñ­­ë© ¨§ OpenFilePlugin ®¯¨á â¥«ì.
dirinfo_start - á ª ª®£® ä ©«  ç¨â âì, dirinfo_size - ᪮«ìª® ä ©«®¢ ç¨â âì.
‚®§¢à é ¥¬®¥ §­ ç¥­¨¥ ¨ ¢®§¢à é ¥¬ë¥ ¢ dirdata ¤ ­­ë¥ ¤®«¦­ë ᮮ⢥âá⢮¢ âì ä㭪樨 70.1.
 
bool __stdcall SetFolder(HANDLE hPlugin, const char* relative_path, const char* absolute_path);
“áâ ­®¢¨âì ⥪ãéãî ¯ ¯ªã. relative_path - ®â­®á¨â¥«ì­ë© ¯ãâì (".." ¨«¨ ¨¬ï ¯®¤¯ ¯ª¨),
absolute_path -  ¡á®«îâ­ë© ¯ãâì (¯ ¯ª  í¬ã«¨à㥬®© ¯« £¨­®¬ ä ©«®¢®© á¨á⥬ë).
 
void __stdcall GetFiles(HANDLE hPlugin, int NumItems, void* items[], void* addfile, void* adddir);
bool __stdcall addfile(const char* name, void* bdfe_info, HANDLE hFile);
bool __stdcall adddir(const char* name, void* bdfe_info);
‚ë§ë¢ ¥âáï ¤«ï ª®¯¨à®¢ ­¨ï, ¥á«¨ ¢® ä« £ å, ¢®§¢à é ¥¬ëå GetOpenPluginInfo, ãáâ ­®¢«¥­ ¡¨â 1.
âã äã­ªæ¨î ४®¬¥­¤ã¥âáï ॠ«¨§®¢ë¢ âì ¢ á«ãç ¥, ¥á«¨ áâ ­¤ àâ­ë© ४ãàᨢ­ë© ®¡å®¤ ¯ ¯®ª
­¥ã¤®¡¥­.
hPlugin - ®¯¨á â¥«ì, ᮧ¤ ­­ë© ¢ OpenFilePlugin.
NumItems - ç¨á«® ª®¯¨à㥬ëå í«¥¬¥­â®¢.
items - ¬ áᨢ ª®¯¨à㥬ëå í«¥¬¥­â®¢, ª ¦¤ë© ¨§ ª®â®àëå § ¤ ñâáï 㪠§ â¥«¥¬ ­  áâàãªâãàã BDFE.
‘¯¥æ¨ «ì­ë© á«ãç © NumItems=-1, items=NULL ®§­ ç ¥â "¢á¥ ä ©«ë" (¢ ⥪ã饩 ¯ ¯ª¥ ¨ ¯®¤¯ ¯ª å).
addfile, adddir - callback-ä㭪樨 kfar' . ‚®§¢à â false ®§­ ç ¥â "¯à¥à¢ âì ª®¯¨à®¢ ­¨¥".
 à ¬¥âà name ¤®«¦¥­ § ¤ ¢ âì ¨¬ï ®â­®á¨â¥«ì­® ⥪ã饩 ¯ ¯ª¨.  à ¬¥âà bdfe_info -
㪠§ â¥«ì ­  ᮪à éñ­­ãî (40 ¡ ©â) § ¯¨áì ¢ ä®à¬ â¥ ä㭪樨 70.5.
Žâªàë⨥¬ ¨ § ªàë⨥¬ ®¯¨á â¥«ï hFile ¤®«¦¥­ § ­¨¬ âìáï ¯« £¨­. ”ã­ªæ¨ï addfile ¡ã¤¥â
¢ë§ë¢ âì ⮫쪮 äã­ªæ¨î read.
 
int __stdcall getattr(HANDLE hPlugin, const char* filename, void* info);
®«ãç¨âì ¨­ä®à¬ æ¨î ® ä ©«¥. ‚®§¢à é ¥¬®¥ §­ ç¥­¨¥ ¨ ¤ ­­ë¥ ¢ info ¤®«¦­ë ᮮ⢥âá⢮¢ âì
ä㭪樨 70.5.
 
HANDLE __stdcall open(HANDLE hPlugin, const char* filename, int mode);
Žâªàëâì ä ©« filename.  à ¬¥âà mode § à¥§¥à¢¨à®¢ ­ ¨ ¢ ⥪ã饩 ¢¥àᨨ kfar ¢á¥£¤  à ¢¥­ 1.
 
unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
—⥭¨¥ size ¡ ©â ¢ ¡ãä¥à buf ¨§ ä ©«  hFile, à ­¥¥ ®âªàë⮣® ç¥à¥§ open.
kfar £ à ­â¨àã¥â, çâ® size ªà â¥­ 512 ¡ ©â.
‚®§¢à é ¥¬®¥ §­ ç¥­¨¥: ç¨á«® ¯à®ç¨â ­­ëå ¡ ©â, -1 ¯à¨ ®è¨¡ª¥.
 
void __stdcall setpos(HANDLE hFile, __int64 pos);
“áâ ­®¢¨âì ⥪ãéãî ¯®§¨æ¨î ¢ ä ©«¥ hFile, à ­¥¥ ®âªàë⮣® ç¥à¥§ open, ¢ pos.
ƒ à ­â¨àã¥âáï, çâ® pos ªà â­® 512 ¡ ©â.
 
void __stdcall close(HANDLE hFile);
/programs/fs/kfar/trunk/dialogs.inc
320,8 → 320,7
jz .redraw
dec eax
jz .key
or eax, -1
int 40h
jmp exit
.redraw:
push ebx ebp
call draw_window
772,6 → 771,10
jz .pgdn
cmp al, 0x49
jz .pgup
cmp al, 0x52
jz .ins
cmp al, 0x53
jz .del
mov edx, [ebx+36]
@@:
cmp dword [edx+4], 0
858,6 → 861,28
.enter:
mov eax, [ebx+36]
ret 16
.ins:
push 5
pop edx
jmp @f
.del:
push 4
pop edx
@@:
mov eax, [ebx+36]
cmp byte [eax+8], '/'
jnz @f
cmp word [eax+9], 'cd'
jnz @f
movzx ecx, byte [eax+11]
sub ecx, '0'
push 24
pop eax
mov ebx, edx
int 40h
@@:
xor eax, eax
ret 16
 
.line_prev:
cmp eax, [ebx+44]
1016,6 → 1041,7
; 8 = í«¥¬¥­â ¬®¦¥â ¨¬¥âì 䮪ãá ¢¢®¤ 
; 10h: ¤«ï ª­®¯ª¨ = ª­®¯ª  ¯® 㬮«ç ­¨î (Enter ­  ­¥-ª­®¯ª¥)
; ¤«ï ¯®«ï ¢¢®¤  = ¤ ­­ë¥ ¡ë«¨ ¬®¤¨ä¨æ¨à®¢ ­ë
; 20h: ¤«ï ¯®«ï ¢¢®¤  = ­¥ ®â®¡à ¦ âì ¢¢®¤¨¬ë¥ ¤ ­­ë¥ (¯®ª §ë¢ âì '*')
.size = $
end virtual
; struct DLGDATA
1309,7 → 1335,8
draw_text_esi:
test esi, esi
jz .ret
or ecx, -1
push -1
pop ecx
@@:
inc ecx
cmp byte [ecx+esi], 0
1372,6 → 1399,14
sub esi, ecx
.text_copy:
jecxz .ret
; check for password editboxes
cmp [ebx+dlgitemtemplate.type], 3
jnz @f
test [ebx+dlgitemtemplate.flags], 20h
jz @f
mov al, '*'
rep stosw
jmp .ret
@@:
lodsb
stosw
1441,31 → 1476,30
call DialogBox
ret
 
; int __stdcall SayErr(const char* title, int x, int y,
; int num_strings, const char* strings[],
; int __stdcall SayErr(int num_strings, const char* strings[],
; int num_buttons, const char* buttons[]);
; may be x=-1 and/or y=-1
SayErr:
pop eax
push aError
push eax
push 2
jmp @f
 
; int __stdcall Message(const char* title, int x, int y,
; int __stdcall Message(const char* title,
; int num_strings, const char* strings[],
; int num_buttons, const char* buttons[]);
Message:
push 1
@@:
pop eax
; [esp+4] = title
; [esp+8] = x
; [esp+12] = y
; [esp+16] = num_strings
; [esp+20] = strings
; [esp+24] = num_buttons
; [esp+28] = buttons
pop eax
; [esp+8] = num_strings
; [esp+12] = strings
; [esp+16] = num_buttons
; [esp+20] = buttons
pushad
mov ecx, [esp+4+16]
add ecx, [esp+4+24]
mov ecx, [esp+32+8]
add ecx, [esp+32+16]
imul ecx, dlgitemtemplate.size
add ecx, dlgtemplate.size+12
call xpgalloc
1479,13 → 1513,12
mov edi, eax
mov eax, [esp+28]
stosd ; dlgtemplate.flags
mov eax, [esp+32+8]
or eax, -1
stosd ; dlgtemplate.x
mov eax, [esp+32+12]
stosd ; dlgtemplate.y
; calculate width
mov ecx, [esp+32+16]
mov esi, [esp+32+20]
mov ecx, [esp+32+8]
mov esi, [esp+32+12]
xor edx, edx
.calcwidth:
lodsd
1500,8 → 1533,8
mov edx, eax
@@:
loop .calcwidth
mov ecx, [esp+32+24]
mov esi, [esp+32+28]
mov ecx, [esp+32+16]
mov esi, [esp+32+20]
xor ebp, ebp
.calcwidth2:
lodsd
1527,7 → 1560,7
@@:
mov eax, edx
stosd ; dlgtemplate.width
mov eax, [esp+32+16]
mov eax, [esp+32+8]
inc eax
stosd ; dlgtemplate.height
mov eax, 3
1540,12 → 1573,12
stosd ; (ignored)
stosd ; DlgProc
stosd ; userdata
mov eax, [esp+32+16]
add eax, [esp+32+24]
mov eax, [esp+32+8]
add eax, [esp+32+16]
stosd ; num_items
; fill strings
xor ecx, ecx
mov esi, [esp+32+20]
mov esi, [esp+32+12]
@@:
mov eax, 1
stosd ; dlgitemtemplate.type
1561,11 → 1594,11
mov eax, 1
stosd ; dlgitemtemplate.flags
inc ecx
cmp ecx, [esp+32+16]
cmp ecx, [esp+32+8]
jb @b
; fill buttons
mov ecx, [esp+32+24]
mov esi, [esp+32+28]
mov ecx, [esp+32+16]
mov esi, [esp+32+20]
sub edx, ebp
jc .big
shr edx, 1
1596,7 → 1629,7
mov eax, [esi-4]
stosd ; dlgitemtemplate.data
mov eax, 9
cmp ecx, [esp+32+24]
cmp ecx, [esp+32+16]
jnz @f
or al, 4
@@:
1611,10 → 1644,10
xor edx, edx
mov ecx, dlgitemtemplate.size
div ecx
sub eax, [esp+32+16]
sub eax, [esp+32+8]
@@:
mov [esp+28], eax
mov ecx, ebx
call pgfree
popad
ret 28
ret 20
/programs/fs/kfar/trunk/filetool.inc
29,9 → 29,6
push 4
push eax
push 3
push -1
push -1
push aError
call SayErr
add esp, 3*4
cmp al, -1
66,6 → 63,8
mov esi, [esp+28]
mov ecx, esi
add esi, 40
cmp byte [edi-1], '/'
jz .l1
mov al, '/'
stosb
.l1:
239,9 → 238,6
push dword [eax+16]
push eax
push 3
push -1
push -1
push dword aError
call SayErr
add esp, 3*4
test eax, eax
253,6 → 249,9
; in: execdata = source name, CopyDestEditBuf+12 = destination name, edx = BDFE block for source
; out: CF and ZF not set <=> cancel job ("ja cancel_label")
; destroys eax,esi,edi
lea edi, [edx+40]
and [source_hFile], 0
copy_file_worker2:
push CopyDestEditBuf+12+513
cmp [bDestIsFolder], 0
jz .noaddtoname
261,12 → 260,16
lodsb
test al, al
jnz @b
mov byte [esi-1], '/'
pop edi
pop eax
dec esi
push esi
mov edi, esi
lea esi, [edx+40]
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
xchg esi, edi
@@:
cmp edi, CopyDestEditBuf+12+513
jae .overflow
lodsb
277,12 → 280,14
.overflow:
.ret_zf:
pop esi
and byte [esi-1], 0 ; ZF=1
and byte [esi], 0 ; ZF=1
ret
.noaddtoname:
; Íåëüçÿ ñêîïèðîâàòü ôàéë ïîâåðõ ñàìîãî ñåáÿ!
; ¥«ì§ï ᪮¯¨à®¢ âì ä ©« ¯®¢¥àå á ¬®£® ᥡï!
mov esi, execdata
mov edi, CopyDestEditBuf+12
cmp [source_hModule], 0
jnz @f
push esi edi
call strcmpi
pop edi esi
294,15 → 299,12
push 1
push eax
push 2
push -1
push -1
push aError
call SayErr
pop eax
pop eax
jmp .ret_zf
@@:
; Ñîáñòâåííî, êîïèðóåì
; ‘®¡á⢥­­®, ª®¯¨à㥬
; esi->source name, edi->destination name
push ebx
mov [writeinfo.code], 2
316,8 → 318,40
mov [ebx+readinfo.size-readinfo], copy_buffer_size
mov [ebx+readinfo.data-readinfo], copy_buffer
mov [ebx+readinfo.name-readinfo], esi
mov eax, [source_hFile]
push eax
test eax, eax
jnz .copyloop
.source_reopen:
mov eax, [source_hModule]
test eax, eax
jz .copyloop
pushad
push O_READ+O_SEQUENTIAL_ONLY
push esi
push [source_hPlugin]
call [eax+PluginInfo.open]
mov [source_hFile], eax
popad
.copyloop:
mov ebx, readinfo
mov eax, [source_hModule]
test eax, eax
jz .native
mov ecx, [source_hFile]
jecxz .readerr
pushad
push [ebx+readinfo.size-readinfo]
push [ebx+readinfo.data-readinfo]
push ecx
call [eax+PluginInfo.read]
mov [esp+28], eax
popad
cmp eax, -1
jz .readerr
mov ebx, eax
jmp .copyreadok
.native:
push 70
pop eax
int 0x40
325,6 → 359,7
jz .copyreadok
cmp eax, 6
jz .copyreadok
.readerr:
cmp [copy_bSkipAll2], 0
jnz .copyfailed_del2
push esi
336,14 → 371,15
push 4
push eax
push 3
push -1
push -1
push dword aError
call SayErr
add esp, 3*4
test eax, eax
jnz .copyfailed_parseuser
cmp [source_hModule], 0
jz .copyloop
jmp .copyfailed_parseuser
cmp [source_hFile], 0
jz .source_reopen
jmp .copyloop
.copyreadok:
add dword [readinfo.first], ebx
adc dword [readinfo.first+4], 0
370,9 → 406,6
push 4
push eax
push 3
push -1
push -1
push dword aError
call SayErr
add esp, 3*4
test eax, eax
394,6 → 427,19
cmp ecx, copy_buffer_size
jz .copyloop
.copydone:
pop ecx
test ecx, ecx
jnz @f
mov eax, [source_hModule]
test eax, eax
jz @f
mov ecx, [source_hFile]
jecxz @f
push edx
push ecx
call [eax+PluginInfo.close]
pop edx
@@:
; now try to set attributes from source, ignore errors
mov edi, attrinfo.attr
mov esi, edx
400,6 → 446,29
push 8
pop ecx
rep movsd
; replace zero dates with default values
mov eax, [default_attr]
cmp dword [edi-32+8], 0
jnz @f
mov ecx, [eax+8]
mov [edi-32+8], ecx
mov ecx, [eax+12]
mov [edi-32+12], ecx
@@:
cmp dword [edi-32+16], 0
jnz @f
mov ecx, [eax+16]
mov [edi-32+16], ecx
mov ecx, [eax+20]
mov [edi-32+20], ecx
@@:
cmp dword [edi-32+24], 0
jnz @f
mov ecx, [eax+24]
mov [edi-32+24], ecx
mov ecx, [eax+28]
mov [edi-32+28], ecx
@@:
mov ebx, attrinfo
mov [ebx+attrinfo.name-attrinfo], CopyDestEditBuf+12
inc dword [ebx]
413,12 → 482,23
.ret:
pop ebx
pop esi
mov byte [esi-1], 0
mov byte [esi], 0
ret
.copydone2:
popf
jmp .ret
.copyfailed:
pop ecx
test ecx, ecx
jnz @f
mov eax, [source_hModule]
test eax, eax
jz @f
mov ecx, [source_hFile]
jecxz @f
push ecx
call [eax+PluginInfo.close]
@@:
cmp [bConfirmDeleteIncomplete], 0
jz .copyfailed_del
cmp [writeinfo.code], 2
429,10 → 509,8
push 2
push eax
push 1
push -1
push -1
push dword aCopyCaption
call SayErr
call Message
add esp, 4
test eax, eax
jnz .copydone2
468,6 → 546,8
@@:
mov esi, [esp+28]
add esi, 40
cmp byte [edi-1], '/'
jz .l1
mov al, '/'
stosb
.l1:
475,6 → 555,7
cmp edi, execdataend
jb @f
call panels_OnKey.bigfilename
stc
popad
ret
@@:
504,7 → 585,12
lodsb
test al, al
jnz @b
mov byte [esi-1], '/'
dec esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
mov edi, esi
lea esi, [edx+40]
@@:
527,8 → 613,44
@@:
cmp al, 1
jz .copy_dir_entry_done
jmp .cancel
jmp .cancel2
.target_created:
mov edx, [source_hModule]
test edx, edx
jz .nosetdir
mov esi, execdata
push esi ; absolute_path
@@:
lodsb
test al, al
jnz @b
@@:
dec esi
cmp byte [esi-1], '/'
jnz @b
push esi ; relative_path
push [source_hPlugin] ; hPlugin
call [edx+PluginInfo.SetFolder]
test al, al
jnz .nosetdir
cmp [copy_bSkipAll3], 0
jz .skip2
push execdata
push aCannotSetFolder
mov eax, esp
push DeleteErrorBtn
push 4
push eax
push 2
call SayErr
pop ecx ecx
test al, al
jz .target_created
cmp al, 2
setz [copy_bSkipAll3]
ja .cancel2
jmp .skip2
.nosetdir:
xor ebp, ebp ; ebp will contain number of copied items
.return_from_recursion:
.read_retry:
537,9 → 659,23
mov [ebx+dirinfo.size-dirinfo], copy_dir_query_size
mov [ebx+dirinfo.dirdata-dirinfo], copy_dir_query_area
mov [ebx+dirinfo.name-dirinfo], execdata
mov eax, [source_hModule]
test eax, eax
jz .readfolder_native
push ebp
push [ebx+dirinfo.dirdata-dirinfo]
push [ebx+dirinfo.size-dirinfo]
push [ebx+dirinfo.first-dirinfo]
push [source_hPlugin]
call [eax+PluginInfo.ReadFolder]
pop ebp
mov ebx, dword [copy_dir_query_area+4]
jmp @f
.readfolder_native:
push 70
pop eax
int 0x40
@@:
test eax, eax
jz .readok
cmp eax, 6
546,7 → 682,7
jz .readok
; read error
cmp [copy_bSkipAll], 0
jz .skip1
jnz .skip1
push execdata
push aCannotReadFolder
call get_error_msg
556,9 → 692,6
push 4
push eax
push 3
push -1
push -1
push aError
call SayErr
add esp, 3*4
test al, al
597,7 → 730,12
lodsb
test al, al
jnz @b
mov byte [esi-1], '/'
dec esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
mov edi, esi
lea esi, [edx+40]
@@:
612,7 → 750,12
lodsb
test al, al
jnz @b
mov byte [esi-1], '/'
dec esi
cmp byte [esi-1], '/'
jz @f
mov byte [esi], '/'
inc esi
@@:
mov edi, esi
lea esi, [edx+40]
@@:
625,7 → 768,7
test byte [edx], 10h
jnz .entry_is_folder
call copy_file_worker
ja .cancel
ja .cancel3
jmp .restore_name
.entry_is_folder:
; allocate new item in directory stack
642,7 → 785,6
.fullname2_big:
mov esi, CopyDestEditBuf+12+512
jmp .restore_name2
.skip1:
.restore_name:
mov esi, CopyDestEditBuf+12
@@:
665,8 → 807,23
.copy_dir_entry_continue:
add edx, 304
jmp .copy_dir_entry_loop
.skip1:
.copy_dir_entry_done:
; return to previous directory
mov esi, execdata
call delete_last_name_from_end
mov eax, [source_hModule]
test eax, eax
jz @f
push execdata
push aDotDot
push [source_hPlugin]
call [eax+PluginInfo.SetFolder]
jmp @f
.skip2:
mov esi, execdata
call delete_last_name_from_end
@@:
; pop item from directory stack
mov ecx, [copy_dir_stack_ptr]
cmp ecx, copy_dir_stack
675,16 → 832,34
mov [copy_dir_stack_ptr], ecx
mov ebp, [ecx]
; restore prev directory name
mov esi, execdata
call delete_last_name_from_end
mov esi, CopyDestEditBuf+12
call delete_last_name_from_end
jmp .return_from_recursion
.done:
.cancel:
mov [dirinfo.first], 0 ; do not destroys flags
popad
ret
.cancel2:
sub [copy_dir_stack_ptr], 4
.cancel3:
mov esi, execdata
call delete_last_name_from_end
.cancel:
mov eax, [source_hModule]
test eax, eax
jz .cancel.ret
cmp [copy_dir_stack_ptr], copy_dir_stack
jb .cancel.ret
push execdata
push aDotDot
push [source_hPlugin]
call [eax+PluginInfo.SetFolder]
jmp .cancel2
.cancel.ret:
xor eax, eax
inc eax
popad
ret
 
delete_last_name_from_end:
lodsb
699,5 → 874,403
cmp al, '/'
jnz @b
cld
inc esi
cmp esi, execdata
jz @f
cmp esi, CopyDestEditBuf+12
jz @f
dec esi
@@:
mov byte [esi+1], 0
ret
 
copy_AddDir:
push 1
pop eax ; for "return true"
pushad
mov esi, CopyDestEditBuf+12
@@:
lodsb
test al, al
jnz @b
cmp byte [esi-2], '/'
jnz @f
dec esi
@@:
push dword [esi-1]
push esi
mov byte [esi-1], '/'
mov edi, esi
mov esi, [esp+28h+4]
.0:
lodsb
stosb
cmp edi, CopyDestEditBuf+12+512
jae .done
test al, al
jnz .0
push RetryOrCancelBtn
push 2
call makedir
jz .done
and dword [esp+8+1Ch], 0
.done:
pop esi
pop dword [esi-1]
popad
ret 8
 
copy_AddFile:
pushad
mov eax, [esp+20h+12]
mov [source_hFile], eax
mov edx, [esp+20h+8]
mov edi, [esp+20h+4]
call copy_file_worker2
popad
setna al
ret 12
 
virtual at 0
_FILE:
.pos dq ?
.bufpos dq ?
.bufsize dd ?
.mode dd ?
.hPlugin dd ?
.hFile dd ?
.fileinfo:
.fimode dd ?
.fioffset dq ?
.fisize dd ?
.fibuf dd ?
.finame rb 1024
.attr rb 40
align 512
.buf rb 2048
.size = $
end virtual
 
O_READ = 1 ; allows read from file
O_WRITE = 2 ; allows write to file
O_CREATE = 4 ; if file does not exist and this flag is set, create file;
; if file does not exist and this flag is not set, fail
O_TRUNCATE = 8 ; truncate file if it exists
O_SEQUENTIAL_ONLY = 10h ; there will be no 'seek'/'setpos' calls
 
; HANDLE __stdcall open(const char* name, int mode);
; Opens physical file
open:
pushad
mov ecx, _FILE.size
call xpgalloc
test eax, eax
jz .ret0z
mov [esp+28], eax
mov ecx, eax
mov esi, [esp+36]
lea edi, [eax+_FILE.finame]
lea edx, [eax+_FILE.finame+1024]
@@:
lodsb
stosb
test al, al
jz @f
cmp edi, edx
jb @b
.ret0:
call pgfree
.ret0z:
popad
xor eax, eax
ret 8
@@:
mov eax, [esp+40]
mov [ecx+_FILE.mode], eax
.getattr:
lea edi, [ecx+_FILE.fileinfo]
mov ebx, edi
push 5
pop eax
stosd
xor eax, eax
stosd
stosd
stosd
lea eax, [ecx+_FILE.attr]
stosd
push 70
pop eax
int 0x40
test eax, eax
jz .found
cmp eax, 5
jnz .ret0
; file does not exist
test [ecx+_FILE.mode], O_CREATE
jz .ret0z
.truncate:
lea ebx, [ecx+_FILE.fileinfo]
mov byte [ebx], 2
push 70
pop eax
int 0x40
test eax, eax
jz .getattr
jmp .ret0
.found:
test [ecx+_FILE.mode], O_TRUNCATE
jz @f
cmp dword [ecx+_FILE.attr+36], eax
jnz .truncate
cmp dword [ecx+_FILE.attr+32], eax
jnz .truncate
@@:
mov dword [ecx+_FILE.pos], eax
mov dword [ecx+_FILE.pos+4], eax
mov dword [ecx+_FILE.bufpos], eax
mov dword [ecx+_FILE.bufpos+4], eax
mov [ecx+_FILE.bufsize], eax
mov [ecx+_FILE.hPlugin], eax
mov [ecx+_FILE.hFile], eax
mov dword [ecx+_FILE.fioffset], eax
mov dword [ecx+_FILE.fioffset+4], eax
mov [esp+28], ecx
popad
ret 8
 
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
read:
xor eax, eax
pushad
mov ecx, [esp+36]
test [ecx+_FILE.mode], O_READ
jnz @f
.ret:
popad
ret 12
@@:
cmp dword [esp+44], eax
jz .ret
mov [ecx+_FILE.fimode], eax
mov ebx, [ecx+_FILE.bufsize]
mov eax, dword [ecx+_FILE.pos]
and eax, 2047
sub ebx, eax
jbe .nobuf0
cmp ebx, [esp+44]
jbe @f
mov ebx, [esp+44]
@@:
push ecx
lea esi, [ecx+eax+_FILE.buf]
mov ecx, ebx
mov edi, [esp+44]
rep movsb
pop ecx
mov [esp+40], edi
add [esp+28], ebx
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
sub [esp+44], ebx
jz .ret
.nobuf0:
test dword [ecx+_FILE.pos], 2047
jz .aligned
cmp dword [ecx+_FILE.bufsize], 0
jnz .ret
lea ebx, [ecx+_FILE.fileinfo]
mov dword [ebx+12], 2048
lea eax, [ecx+_FILE.buf]
mov dword [ebx+16], eax
mov eax, dword [ecx+_FILE.fioffset]
mov dword [ecx+_FILE.bufpos], eax
mov eax, dword [ecx+_FILE.fioffset+4]
mov dword [ecx+_FILE.bufpos+4], eax
call .doread
test eax, eax
jnz .ret
mov [ecx+_FILE.bufsize], ebx
mov eax, dword [ecx+_FILE.pos]
and eax, 2047
sub ebx, eax
jbe .ret
cmp ebx, [esp+44]
jbe @f
mov ebx, [esp+44]
@@:
push ecx
lea esi, [ecx+eax+_FILE.buf]
mov ecx, ebx
mov edi, [esp+44]
rep movsb
pop ecx
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
mov [esp+40], edi
add [esp+28], ebx
sub [esp+44], ebx
jz .ret
test dword [ecx+_FILE.pos], 2047
jnz .ret
.aligned:
lea ebx, [ecx+_FILE.fileinfo]
mov eax, [esp+44]
and eax, not 2047
jz .finish
and [ecx+_FILE.bufsize], 0
mov [ebx+12], eax
mov eax, [esp+40]
mov [ebx+16], eax
call .doread
test eax, eax
jnz .ret
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
add [esp+28], ebx
add [esp+40], ebx
sub [esp+44], ebx
jz .ret
cmp ebx, [ecx+_FILE.fisize]
jb .ret
.finish:
lea ebx, [ecx+_FILE.fileinfo]
mov dword [ebx+12], 2048
lea eax, [ecx+_FILE.buf]
mov [ebx+16], eax
and [ecx+_FILE.bufsize], 0
mov eax, dword [ecx+_FILE.fioffset]
mov dword [ecx+_FILE.bufpos], eax
mov eax, dword [ecx+_FILE.fioffset+4]
mov dword [ecx+_FILE.bufpos+4], eax
call .doread
test eax, eax
jnz .ret
mov [ecx+_FILE.bufsize], ebx
cmp ebx, [esp+44]
jb @f
mov ebx, [esp+44]
@@:
add [esp+28], ebx
add dword [ecx+_FILE.pos], ebx
adc dword [ecx+_FILE.pos+4], 0
lea esi, [ecx+_FILE.buf]
mov edi, [esp+40]
mov ecx, ebx
rep movsb
popad
ret 12
.doread:
mov eax, [ecx+_FILE.hPlugin]
test eax, eax
jz .native
push ecx
push [ecx+_FILE.fisize]
push [ecx+_FILE.fibuf]
push [ecx+_FILE.hFile]
call [eax+PluginInfo.read]
pop ecx
cmp eax, -1
jz @f
mov ebx, eax
xor eax, eax
jmp .addpos
@@:
ret
.native:
push 70
pop eax
int 0x40
test eax, eax
jz .addpos
cmp eax, 6
jnz @b
xor eax, eax
.addpos:
add dword [ecx+_FILE.fioffset], ebx
adc dword [ecx+_FILE.fioffset+4], 0
ret
 
; void __stdcall seek(HANDLE hFile, int method, __int64 newpos);
seek:
pushad
mov ecx, [esp+36]
mov eax, [esp+44]
mov edx, [esp+48]
cmp dword [esp+40], 1
jb .set
ja .end
add eax, dword [ecx+_FILE.pos]
adc edx, dword [ecx+_FILE.pos+4]
jmp .set
.end:
add eax, dword [ecx+_FILE.attr+32]
adc edx, dword [ecx+_FILE.attr+36]
.set:
mov dword [ecx+_FILE.pos], eax
mov dword [ecx+_FILE.pos+4], edx
and eax, not 2047
cmp eax, dword [ecx+_FILE.bufpos]
jnz @f
cmp edx, dword [ecx+_FILE.bufpos+4]
jz .bufposok
@@:
and [ecx+_FILE.bufsize], 0
mov dword [ecx+_FILE.bufpos], eax
mov dword [ecx+_FILE.bufpos+4], edx
.bufposok:
cmp [ecx+_FILE.bufsize], 0
jnz .ret
cmp eax, dword [ecx+_FILE.fioffset]
jnz @f
cmp edx, dword [ecx+_FILE.fioffset+4]
jz .ret
@@:
mov dword [ecx+_FILE.fioffset], eax
mov dword [ecx+_FILE.fioffset+4], edx
mov eax, [ecx+_FILE.hPlugin]
test eax, eax
jz @f
push dword [ecx+_FILE.fioffset+4]
push dword [ecx+_FILE.fioffset]
push [ecx+_FILE.hFile]
call [eax+PluginInfo.setpos]
@@:
.ret:
popad
ret 16
 
setpos_default:
push dword [esp+12]
push dword [esp+12]
push 0
push dword [esp+16]
call seek
ret 12
 
; __int64 __stdcall filesize(HANDLE hFile);
filesize:
mov eax, [esp+4]
mov edx, dword [eax+_FILE.attr+36]
mov eax, dword [eax+_FILE.attr+32]
ret 4
 
; void __stdcall close(HANDLE hFile);
close:
pushad
mov ecx, [esp+24h]
mov eax, [ecx+_FILE.hPlugin]
test eax, eax
jz @f
push ecx
push [ecx+_FILE.hFile]
call [eax+PluginInfo.close]
pop ecx
@@:
call pgfree
popad
ret 4
 
getattr_default:
mov eax, 2
ret 12
/programs/fs/kfar/trunk/kfar.asm
7,6 → 7,9
dd stacktop
dd 0, app_path
 
version equ '0.4'
version_dword equ 0*10000h + 40
 
include 'lang.inc'
include 'font.inc'
include 'sort.inc'
81,10 → 84,18
jz exit
cmp [panel1_files], 0
jz exit
mov [panel1_sortmode], 0 ; sort by name
mov [panel2_sortmode], 0
push 2 ; "á।­¨©" ä®à¬ â
pop eax
xor eax, eax
mov [panel1_hPlugin], eax
mov [panel1_parents], eax
mov [panel1_parents_sz], eax
mov [panel1_parents_alloc], eax
mov [panel2_hPlugin], eax
mov [panel2_parents], eax
mov [panel2_parents_sz], eax
mov [panel2_parents_alloc], eax
mov [panel1_sortmode], al ; sort by name
mov [panel2_sortmode], al
mov al, 2 ; "á।­¨©" ä®à¬ â
mov [panel1_colmode], eax
mov [panel2_colmode], eax
mov [num_screens], 1
121,6 → 132,28
push dword app_path
call [ini.get_int]
mov [bConfirmDeleteIncomplete], al
push 2
push aLeftViewMode
push aPanels
push app_path
call [ini.get_int]
cmp eax, 1
jb @f
cmp eax, 4
ja @f
mov [panel1_colmode], eax
@@:
push 2
push aRightViewMode
push aPanels
push app_path
call [ini.get_int]
cmp eax, 1
jb @f
cmp eax, 4
ja @f
mov [panel2_colmode], eax
@@:
mov ecx, 0x1000
call xpgalloc
test eax, eax
202,6 → 235,11
@@:
loop .l3
.skip_shortcuts:
; load plugins
push enum_plugins_callback
push aPlugins
push app_path
call [ini.enum_keys]
.noini:
mov esi, def_left_dir
mov edi, panel1_dir
239,6 → 277,86
jz key
; button - we have only one button, close
exit:
; close all screens
@@:
mov ecx, [num_screens]
mov eax, [screens]
mov ebp, [eax+ecx*8-4]
mov eax, [eax+ecx*8-8]
push ebp
call [eax+screen_vtable.OnExit]
pop ecx
call pgfree
dec [num_screens]
jnz @b
; unload all plugins
mov ecx, [num_plugins]
imul esi, ecx, PluginInfo.size
add esi, [plugins]
.unload:
dec ecx
js .unload_done
sub esi, PluginInfo.size
push ecx esi
call [esi+PluginInfo.unload]
pop esi ecx
jmp .unload
.unload_done:
if 0 ; commented due to bug in libini
cmp [ini.set_int], aIniSetInt
jz .nosave
push [panel1_colmode]
push aLeftViewMode
push aPanels
push app_path
call [ini.set_int]
push [panel2_colmode]
push aRightViewMode
push aPanels
push app_path
call [ini.set_int]
.nosave:
end if
if CHECK_FOR_LEAKS
mov ecx, [panel1_files]
call pgfree
mov ecx, [panel2_files]
call pgfree
mov ecx, [screens]
call pgfree
mov ecx, [associations]
call pgfree
mov ecx, [console_data_ptr]
call pgfree
mov ecx, [MemForImage]
call pgfree
mov esi, FolderShortcuts
push 10
pop ecx
@@:
lodsd
test eax, eax
jnz @f
loop @b
jmp .nofreefs
@@:
mov ecx, eax
call pgfree
mov ecx, [plugins]
call pgfree
mov ecx, [panel1_parents]
call pgfree
mov ecx, [panel2_parents]
call pgfree
.nofreefs:
mov eax, [numallocatedregions]
test eax, eax
jz @f
mov edi, allocatedregions
int3
jmp $
@@:
end if
or eax, -1
int 40h
redraw:
640,6 → 758,182
xor eax, eax
ret 12
 
enum_plugins_callback:
; LongBool __stdcall callback(f_name,sec_name,key_name);
; [esp+4] = f_name, [esp+8] = sec_name, [esp+12] = key_name
push nullstr
push 1024
push saved_file_name
push dword [esp+12+12]
push dword [esp+16+8]
push dword [esp+20+4]
call [ini.get_str]
test eax, eax
jnz .ret
mov esi, saved_file_name
cmp byte [esi], '/'
jz .absolute
; convert path to absolute
mov edi, execdata
push esi
@@:
lodsb
stosb
test al, al
jnz @b
pop edi
mov esi, app_path
push esi
xor ecx, ecx
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
mov ecx, esi
jmp @b
@@:
pop esi
sub ecx, esi
rep movsb
mov esi, execdata
.z:
cmp word [esi], '.'
jz .ret
cmp word [esi], './'
jnz @f
add esi, 2
jmp .z
@@:
cmp word [esi], '..'
jnz .c
cmp byte [esi+2], 0
jz .ret
cmp byte [esi+2], '/'
jnz .c
add esi, 3
@@:
dec edi
cmp edi, saved_file_name
jbe .ret
cmp byte [edi-1], '/'
jnz @b
jmp .z
.c:
lodsb
stosb
test al, al
jz @f
cmp edi, saved_file_name+1024
jb .c
mov esi, execdata
call load_dll_and_import.big
.ret:
mov al, 1
ret 12
@@:
.absolute:
; allocate space for plugin info
mov eax, [num_plugins]
inc eax
mov [num_plugins], eax
imul ecx, eax, PluginInfo.size
cmp ecx, [alloc_plugins]
jbe .norealloc
mov edx, [plugins]
call xpgrealloc
test eax, eax
jnz @f
.dec_ret:
dec [num_plugins]
jmp .ret
@@:
mov [plugins], eax
lea eax, [ecx+0xFFF]
and eax, not 0xFFF
mov [alloc_plugins], eax
.norealloc:
mov esi, [plugins]
lea esi, [esi+ecx-PluginInfo.size]
; load plugin DLL
or ebp, -1
mov eax, saved_file_name
call load_dll_and_import.do
test eax, eax
jnz .dec_ret
; find exported functions
mov eax, aVersion
call load_dll_and_import.find_exported_function
jnc @f
xor eax, eax
@@:
MIN_INTERFACE_VER = 1
MAX_INTERFACE_VER = 1
cmp eax, MIN_INTERFACE_VER
jae @f
cmp eax, MAX_INTERFACE_VER
jbe @f
push aIncompatibleVersion
.cantload:
push saved_file_name
push aCannotLoadPlugin
mov eax, esp
push ContinueBtn
push 1
push eax
push 3
call SayErr
add esp, 12
jmp .dec_ret
@@:
mov edi, esi
mov esi, plugin_exported
.import:
lodsd
test eax, eax
jz .import_done
call load_dll_and_import.find_exported_function
jnc @f
mov eax, [esi-4+plugin_exported_default-plugin_exported]
@@:
stosd
jmp .import
.import_done:
; initialize plugin
mov eax, aPluginLoad
call load_dll_and_import.find_exported_function
jc .ok
push kfar_info
call eax
cmp eax, 1
jb .ok
ja .dec_ret
push aInitFailed
jmp .cantload
.ok:
mov al, 1
ret 12
 
plugin_unload_default:
ret
 
OpenFilePlugin_default:
GetFiles_default:
xor eax, eax
ret 20
 
ClosePlugin_default:
ret 4
 
GetOpenPluginInfo_default:
ret 8
 
SetFolder_default:
open_default:
xor eax, eax
ret 12
 
new_screen:
; in: ecx=sizeof(screen data), edx->vtable
; out: ebp=pointer or NULL, eax!=0 if successful
967,6 → 1261,152
call get_curfile_folder_entry
test byte [ecx], 10h
jnz .enter_folder
; todo: add <Enter> handling on plugin panel
cmp [ebp + panel1_hPlugin - panel1_data], 0
jnz .ret
; generate full file name
lea esi, [ebp + panel1_dir - panel1_data]
mov edi, execdata
@@:
lodsb
test al, al
jz @f
stosb
cmp edi, execdataend-1
jae .bigfilename
jmp @b
@@:
lea esi, [ecx+40]
mov al, '/'
stosb
@@:
lodsb
stosb
cmp edi, execdataend
ja .bigfilename
test al, al
jnz @b
; try to open file and look for all plugins
push O_READ
push execdata
call open
test eax, eax
jz .noplugins ; if can't open, just try to execute
mov esi, eax ; save handle
push filedata_buffer_size
push filedata_buffer
push esi
call read
mov edi, eax ; save size of read data
; test for Kolibri executable
cmp eax, 24h
jb .enter.noexec
cmp dword [filedata_buffer], 'MENU'
jnz @f
cmp word [filedata_buffer+4], 'ET'
jnz @f
.close_run:
push esi
call close
jmp .run_app
@@:
cmp dword [filedata_buffer], 'KPCK'
jnz @f
cmp dword [filedata_buffer+12], 0x26914601
jz .close_run
@@:
.enter.noexec:
mov ecx, [num_plugins]
mov edx, [plugins]
sub edx, PluginInfo.size
.plugloop:
add edx, PluginInfo.size
dec ecx
js .plugdone
pushad
push edi
push filedata_buffer
call get_curfile_folder_entry
push ecx
push execdata
push esi
call [edx+PluginInfo.OpenFilePlugin]
mov [esp+28], eax
popad
test eax, eax
jz .plugloop
cmp eax, -1
jnz .pluginok
push esi
call close
ret
.pluginok:
; save current directory and set root directory of hPlugin
mov edi, eax ; save handle
mov esi, execdata
@@:
lodsb
test al, al
jnz @b
sub esi, execdata-9
; allocate esi bytes in buffer 'parents'
mov ecx, [ebp + panel1_parents_sz - panel1_data]
add ecx, esi
cmp ecx, [ebp + panel1_parents_alloc - panel1_data]
jbe .enter.norealloc
push edx
mov edx, [ebp + panel1_parents - panel1_data]
call xpgrealloc
pop edx
test eax, eax
jnz @f
push edi
call [edx+PluginInfo.ClosePlugin]
ret
@@:
mov [ebp + panel1_parents - panel1_data], eax
.enter.norealloc:
mov [ebp + panel1_parents_sz - panel1_data], ecx
; save current state to the end of buffer
sub ecx, esi
add ecx, [ebp + panel1_parents - panel1_data]
xchg edx, [ebp + panel1_hPlugin - panel1_data]
mov [ecx], edx
xchg edi, [ebp + panel1_hFile - panel1_data]
mov [ecx+4], edi
mov byte [ecx+8], 0
lea edi, [ecx+9]
lea ecx, [esi-9]
mov esi, execdata
rep movsb
mov word [ebp + panel1_dir - panel1_data], '/'
mov eax, [ebp + panel1_hPlugin - panel1_data]
lea ebx, [ebp + panel1_plugin_info - panel1_data]
and dword [ebx], 0
push ebp
push ebx
push [ebp + panel1_hFile - panel1_data]
call [eax+PluginInfo.GetOpenPluginInfo]
pop ebp
call get_curfile_folder_entry
mov esi, ecx
mov edi, left_dotdot_entry
cmp ebp, panel1_data
jz @f
add edi, right_dotdot_entry-left_dotdot_entry
@@:
mov ecx, 10
rep movsd
mov byte [edi-40], 10h ; attributes: folder
mov eax, '..'
stosd
jmp .reread
.plugdone:
push esi
call close
.noplugins:
; run program or association
call get_curfile_folder_entry
call find_extension
jc .run_app
.run_association:
996,27 → 1436,6
mov [execptr], execdata
and [execparams], 0
.dorun:
lea esi, [ebp + panel1_dir - panel1_data]
mov edi, execdata
@@:
lodsb
test al, al
jz @f
stosb
cmp edi, execdataend-1
jae .bigfilename
jmp @b
@@:
lea esi, [ecx+40]
mov al, '/'
stosb
@@:
lodsb
stosb
cmp edi, execdataend
ja .bigfilename
test al, al
jnz @b
; for fasm call - special handling, because
; 1) fasm command line convention is different : fasm infile,outfile[,path] rather than tinypad infile
; 2) fasm will probably create new file in directory, so we want to reload panel data
1096,9 → 1515,6
push 1
push eax
push 2
push -1
push -1
push dword aError
call SayErr
pop eax
pop eax
1133,9 → 1549,6
push 1
push eax
push 1
push -1
push -1
push dword aError
call SayErr
pop eax
ret
1143,7 → 1556,13
mov eax, aCmdLineTooBig
jmp .l2
.bigfoldername2:
mov byte [ecx], 0
mov esi, prev_dir
lea edi, [ebp + panel1_dir - panel1_data]
@@:
lodsb
stosb
test al, al
jnz @b
.bigfoldername:
mov eax, aFolderNameTooBig
jmp .l2
1167,7 → 1586,6
cmp esi, edx
pop esi
jae .bigfoldername
mov ecx, edi
mov al, '/'
cmp [edi-1], al
jz @f
1179,6 → 1597,28
stosb
test al, al
jnz @b
mov eax, [ebp + panel1_hPlugin - panel1_data]
test eax, eax
jz .reread
push ebp
lea esi, [ebp + panel1_dir - panel1_data]
push esi
add ecx, 40
push ecx
push [ebp + panel1_hFile - panel1_data]
call [eax+PluginInfo.SetFolder]
pop ebp
test al, al
jnz .reread
mov esi, prev_dir
lea edi, [ebp + panel1_dir - panel1_data]
@@:
lodsb
stosb
test al, al
jnz @b
.retd:
ret
.reread:
call read_folder
.done_cmdbar:
1186,6 → 1626,14
jmp .done_redraw
.dotdot:
lea edi, [ebp + panel1_dir - panel1_data]
cmp word [edi], '/'
jnz .dotdot_noroot
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz .retd
call close_plugin_panel
jmp .dotdot
.dotdot_noroot:
mov edx, edi
mov al, 0
or ecx, -1
repnz scasb
1195,11 → 1643,37
repnz scasb
cld
inc edi
cmp edi, edx
jnz @f
inc edi
@@:
push dword [edi]
mov byte [edi], 0
inc edi
push edi
mov eax, [ebp + panel1_hPlugin - panel1_data]
test eax, eax
jz .dotdot_native
push ebp
lea esi, [ebp + panel1_dir - panel1_data]
push esi
push aDotDot
push [ebp + panel1_hFile - panel1_data]
call [eax+PluginInfo.SetFolder]
pop ebp
test al, al
jnz .dotdot_native
pop edi
pop dword [edi]
ret
.dotdot_native:
call read_folder
pop edi
pop dword [edi]
push edi
cmp byte [edi], '/'
jnz @f
inc edi
@@:
mov edx, [ebp + panel1_files - panel1_data]
mov ecx, [ebp + panel1_numfiles - panel1_data]
.scanloop:
1228,6 → 1702,8
inc edx
mov [ebp + panel1_start - panel1_data], edx
.scandone:
pop edi
mov byte [edi], 0
jmp .done_cmdbar
.ctrl_f39:
sub al, 0x3D
1356,6 → 1832,10
@@:
mov ecx, edx
lea edi, [ebp + panel1_dir - panel1_data]
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz .find_cur_drive_loop
mov edi, [ebp + panel1_parents - panel1_data]
add edi, 8
.find_cur_drive_loop:
push edi
lea esi, [ecx+8]
1391,15 → 1871,22
push [ebp + panel1_left - panel1_data]
call menu_centered_in
cmp eax, -1
jz .ret2
lea esi, [eax+8]
jnz @f
mov ecx, edx
call pgfree
ret
@@:
push eax
call close_plugin_panels
lea edi, [ebp + panel1_dir - panel1_data]
push ecx esi edi
push edi
mov esi, edi
mov edi, prev_dir
mov ecx, 1024/4
rep movsd
pop edi esi ecx
pop edi
pop esi
add esi, 8
@@:
lodsb
stosb
1410,6 → 1897,11
call read_folder
jmp .done_redraw
.shift_f5:
; todo: copy to plugin panel
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz @f
ret
@@:
mov esi, ebp
cmp [ebp + panel1_selected_num - panel1_data], 0
jnz .f5_2
1429,9 → 1921,23
stosb
jmp @b
.f5:
; todo: copy to plugin panel
mov esi, ebp
xor esi, panel1_data xor panel2_data
cmp [esi + panel1_hPlugin - panel1_data], 0
jz .f5_2
ret
.f5_2:
mov eax, [ebp + panel1_hPlugin - panel1_data]
mov [source_hModule], eax
mov eax, [ebp + panel1_hFile - panel1_data]
mov [source_hPlugin], eax
mov eax, left_dotdot_entry
cmp ebp, panel1_data
jz @f
add eax, right_dotdot_entry-left_dotdot_entry
@@:
mov [default_attr], eax
add esi, panel1_dir - panel1_data
mov edi, CopyDestEditBuf
mov eax, CopyDestEditBuf.length
1699,9 → 2205,6
push 1
push eax
push 2
push -1
push -1
push aError
call SayErr
pop eax
pop eax
1767,6 → 2270,9
mov [bDestIsFolder], dl
mov [copy_bSkipAll], 0
mov [copy_bSkipAll2], 0
mov [copy_bSkipAll3], 0
test [ebp + panel1_plugin_flags - panel1_data], 2
jnz .copy_GetFiles
cmp [ebp + panel1_selected_num - panel1_data], 0
jnz .f5_selected3
call copy_file
1799,6 → 2305,43
loop .f5_selected_copyloop
.f5_multiple_cancel:
jmp .copydone
.copy_GetFiles:
mov ecx, [ebp + panel1_selected_num - panel1_data]
cmp ecx, 1
adc ecx, 0
shl ecx, 2
call xpgalloc
test eax, eax
jnz @f
ret
@@:
push ebp eax ; save
push copy_AddDir ; adddir
push copy_AddFile ; addfile
push eax ; items
shr ecx, 2
push ecx ; NumItems
push [ebp + panel1_hFile - panel1_data]
mov edi, eax
call get_curfile_folder_entry
mov [edi], ecx
cmp [ebp + panel1_selected_num - panel1_data], 0
jz .cgf1
mov esi, [ebp + panel1_files - panel1_data]
mov ecx, [ebp + panel1_numfiles - panel1_data]
.cgf0:
lodsd
test byte [eax+303], 1
jz @f
stosd
@@:
loop .cgf0
.cgf1:
mov eax, [ebp + panel1_hPlugin - panel1_data]
call [eax+PluginInfo.GetFiles]
pop ecx ebp
call pgfree
jmp .copydone
 
.f3:
call view_file
1849,8 → 2392,6
push 2
push eax
push 2
push -1
push -1
push aDeleteCaption
call Message
add esp, 8
1871,6 → 2412,11
.f8_multiple_cancel:
jmp .copydone
.f8:
; todo: delete files from plugin panel
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz @f
ret
@@:
cmp [ebp + panel1_selected_num - panel1_data], 0
jnz .f8_has_selected
call get_curfile_folder_entry
1901,8 → 2447,6
push 2
push eax
push 2
push -1
push -1
push aDeleteCaption
call Message
add esp, 8
1975,6 → 2519,11
@@:
jmp .done_redraw
.menu:
; todo: context menu for plugin panel
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz @f
ret
@@:
; display context menu
; ignore folders
call get_curfile_folder_entry
2253,8 → 2802,10
jnz @f
ret
@@:
push eax
call close_plugin_panels
lea esi, [ebp + panel1_dir - panel1_data]
push eax esi
push esi
mov edi, prev_dir
@@:
lodsb
2383,6 → 2934,113
.galoopdone:
jmp .done_redraw
 
@@:
call close_plugin_panel
close_plugin_panels:
cmp [ebp + panel1_hPlugin - panel1_data], 0
jnz @b
ret
 
close_plugin_panel:
; close plugin and restore old directory
mov esi, [ebp + panel1_parents - panel1_data]
add esi, [ebp + panel1_parents_sz - panel1_data]
@@:
dec esi
cmp byte [esi-1], 0
jnz @b
push esi
lea edi, [ebp + panel1_dir - panel1_data]
@@:
lodsb
stosb
test al, al
jnz @b
pop esi
sub esi, 9
mov edx, [esi] ; hPlugin
mov ebx, [esi+4] ; hFile
sub esi, [ebp + panel1_parents - panel1_data]
mov [ebp + panel1_parents_sz - panel1_data], esi
xchg edx, [ebp + panel1_hPlugin - panel1_data]
xchg ebx, [ebp + panel1_hFile - panel1_data]
push edx ebx
lea ebx, [ebp + panel1_plugin_info - panel1_data]
and dword [ebx], 0
mov eax, [ebp + panel1_hPlugin - panel1_data]
test eax, eax
jz @f
push ebp
push ebx
push [ebp + panel1_hFile - panel1_data]
call [eax+PluginInfo.GetOpenPluginInfo]
pop ebp
@@:
pop ebx edx
 
close_handle_if_unused:
; edx=hPlugin, ebx=hFile
push ebp
xor ecx, ecx
@@:
mov eax, [screens]
mov ebp, [eax+ecx*8+4]
mov eax, [eax+ecx*8]
call [eax+screen_vtable.IsHandleUsed]
jz .used
inc ecx
cmp ecx, [num_screens]
jb @b
push ebx
call [edx+PluginInfo.ClosePlugin]
.used:
pop ebp
ret
 
panels_IsHandleUsed:
; edx=hPlugin, ebx=hFile
mov ebp, panel1_data
call .1
jz .ret
mov ebp, panel2_data
 
.1:
cmp edx, [ebp+panel1_hPlugin-panel1_data]
jnz @f
cmp ebx, [ebp+panel1_hFile-panel1_data]
jz .ret
@@:
mov esi, [ebp + panel1_parents_sz - panel1_data]
test esi, esi
jnz @f
inc esi
.ret:
ret
@@:
add esi, [ebp + panel1_parents - panel1_data]
@@:
dec esi
cmp byte [esi-1], 0
jnz @b
sub esi, 9
cmp edx, [esi] ; hPlugin
jnz .no
mov ebx, [esi+4] ; hFile
jz .ret
.no:
cmp esi, [ebp + panel1_parents - panel1_data]
jnz @b
inc esi
ret
 
panels_OnExit:
; close plugin panels
mov ebp, panel1_data
call close_plugin_panels
mov ebp, panel2_data
call close_plugin_panels
ret
 
panels_OnRedraw:
call draw_cmdbar
mov ebp, panel1_data
2458,12 → 3116,43
end if
sub ecx, 13
mov ebp, [active_panel]
lea esi, [ebp + panel1_dir - panel1_data]
push 3
pop edx
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz .native
mov esi, [ebp + panel1_parents - panel1_data]
add esi, [ebp + panel1_parents_sz - panel1_data]
@@:
dec esi
cmp byte [esi-1], 0
jz @f
cmp byte [esi-1], '/'
jnz @b
@@:
push ecx edi
shr ecx, 1
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
sub edi, [esp]
sub [esp+4], edi
add [esp], edi
pop edi ecx
lea esi, [ebp + panel1_dir - panel1_data]
cmp byte [esi+1], 0
jnz @f
inc esi
@@:
jmp .main
.native:
lea esi, [ebp + panel1_dir - panel1_data]
@@:
lodsb
stosb
dec ecx
test al, al
jz @f
2477,6 → 3166,7
dec esi
dec edi
@@:
.main:
push esi
@@:
lodsb
2518,11 → 3208,11
jz .nodir
cmp esi, [esp]
jae @b
mov esi, [esp+4]
mov al, '/'
stosb
dec ecx
jz .nodir
mov esi, [esp+4]
@@:
cmp esi, [esp+8]
jb .nodir
3058,6 → 3748,44
and dword [edi], 0
ret
 
GetPanelTitle_default:
mov edi, [esp+8]
mov ecx, 1024
mov esi, [esp+12]
test esi, esi
jz .nohost
mov edx, esi
@@:
lodsb
test al, al
jz @f
cmp al, '/'
jnz @b
mov edx, esi
jmp @b
@@:
mov esi, edx
@@:
lodsb
stosb
test al, al
loopnz @b
dec edi
inc ecx
.nohost:
mov esi, [esp+16]
cmp word [esi], '/'
jz .nodir
@@:
lodsb
stosb
test al, al
loopnz @b
dec edi
.nodir:
mov byte [edi], 0
ret 10h
 
draw_panel:
mov eax, [ebp + panel1_left - panel1_data]
mov edx, [ebp + panel1_top - panel1_data]
3182,6 → 3910,24
jnz .columns_loop
; ‡ £®«®¢®ª ¯ ­¥«¨ (⥪ãé ï ¯ ¯ª )
lea esi, [ebp + panel1_dir - panel1_data]
mov eax, [ebp + panel1_hPlugin - panel1_data]
test eax, eax
jz .native
push ebp
push esi
mov esi, [ebp + panel1_parents - panel1_data]
add esi, [ebp + panel1_parents_sz - panel1_data]
@@:
dec esi
cmp byte [esi-1], 0
jnz @b
push esi
push execdata
push [ebp + panel1_hFile - panel1_data]
call [eax+PluginInfo.GetPanelTitle]
pop ebp
mov esi, execdata
.native:
mov edi, cur_header
mov ecx, [ebp + panel1_width - panel1_data]
sub ecx, 7
4038,10 → 4784,30
mov dword [ebp + panel1_selected_size - panel1_data], eax
mov dword [ebp + panel1_selected_size+4 - panel1_data], eax
.retry:
mov eax, [ebp + panel1_hPlugin - panel1_data]
test eax, eax
jz .native
mov ecx, [dirinfo.size]
test [ebp + panel1_plugin_flags - panel1_data], 1
jz @f
dec ecx ; reserve one entry for '..'
@@:
push ebp
push [dirinfo.dirdata]
push ecx
push 0
push [ebp + panel1_hFile - panel1_data]
call [eax + PluginInfo.ReadFolder]
pop ebp
mov ebx, [dirinfo.dirdata]
mov ebx, [ebx+4]
jmp .read
.native:
push 70
pop eax
mov ebx, dirinfo
int 40h
.read:
test eax, eax
jz .ok
cmp eax, 6
4061,14 → 4827,14
push 2
push eax
push 3
push -1
push -1
push dword aError
call SayErr
add esp, 5*4
test eax, eax
jz .retry
.dont_notify:
; If not on plugin panel, try to return to previous directory
cmp [ebp + panel1_hPlugin - panel1_data], 0
jnz @f
mov esi, prev_dir
cmp byte [esi], 0
jz @f
4079,6 → 4845,7
ret
@@:
mov [bSilentFolderMode], 1 ; enter silent mode
; Try to read parent folder
mov esi, [dirinfo.name]
xor edx, edx
.up1:
4091,11 → 4858,27
lea edi, [esi-1]
jmp .up1
.up1done:
cmp [ebp + panel1_hPlugin - panel1_data], 0
jz .4
cmp edx, 1
ja .up
; ç⥭¨¥ á ¯ ­¥«¨ ¯« £¨­  ®¡«®¬ «®áì ¯® ¯®«­®©
; ¯à¨ í⮬ ¬ë 㦥 ¢ ª®à­¥
; ¤¥« ¥¬ ¢¨¤, çâ® äã­ªæ¨ï ç⥭¨ï ¢¥à­ã«  0 í«¥¬¥­â®¢
; (¥á«¨ ­ã¦¥­ ¢å®¤ "..", ®­ ¡ã¤¥â ¤®¡ ¢«¥­  ¢â®¬ â¨ç¥áª¨)
xor ebx, ebx ; 0 items read
mov eax, [dirinfo.dirdata]
mov [eax+8], ebx ; 0 items total
jmp .ok
.4:
cmp edx, 2
jbe .noup
.up:
stosb
jmp read_folder
.noup:
; There is no parent folder, and we are not on plugin panel
; Try to read ramdisk
mov esi, [dirinfo.name]
mov edi, esi
lodsd
4142,9 → 4925,10
mov [prev_dir], 0
jmp read_folder
.readdone:
and [ebp + panel1_start - panel1_data], 0
and [ebp + panel1_index - panel1_data], 0
and [ebp + panel1_start - panel1_data], 0
xor edx, edx
mov [ebp + panel1_start - panel1_data], edx
mov [ebp + panel1_index - panel1_data], edx
mov [ebp + panel1_start - panel1_data], edx
mov edi, [ebp + panel1_files - panel1_data]
mov eax, [ebp + panel1_nfa - panel1_data]
lea eax, [edi + eax*4 + 32]
4151,7 → 4935,6
mov ecx, [eax-32+4]
test ecx, ecx
jz .loopdone
xor edx, edx
; ˆ£­®à¨à㥬 ᯥ樠«ì­ë¥ ¢å®¤ë, ᮮ⢥âáâ¢ãî騥 ¯ ¯ª¥ '.' ¨ ¬¥âª¥ ⮬ 
.ptrinit:
cmp word [eax+40], '.'
4192,6 → 4975,58
.dotdot:
; ¯®¤á¢¥âª 
; call insert_last_dot
call highlight_init
; call delete_last_dot
.loopcont:
add eax, 304
dec ecx
jnz .ptrinit
.loopdone:
push edi
sub edi, [ebp + panel1_files - panel1_data]
shr edi, 2
mov [ebp + panel1_numfiles - panel1_data], edi
pop edi
test edx, edx
jnz @f
test [ebp + panel1_plugin_flags - panel1_data], 1
jz @f
mov ecx, [ebp + panel1_numfiles - panel1_data]
inc [ebp + panel1_numfiles - panel1_data]
lea esi, [edi-4]
std
rep movsd
cld
mov eax, left_dotdot_entry
cmp ebp, panel1_data
jz .zq
add eax, right_dotdot_entry-left_dotdot_entry
.zq:
stosd
call highlight_init
@@:
; ‘®àâ¨à®¢ª 
sort_files:
movzx eax, [ebp + panel1_sortmode - panel1_data]
mov ebx, [compare_fns + eax*4]
.mode:
mov edx, [ebp + panel1_files - panel1_data]
mov ecx, [ebp + panel1_numfiles - panel1_data]
jecxz .skip
mov eax, [edx]
cmp word [eax+40], '..'
jnz .nodotdot
cmp byte [eax+42], 0
jnz .nodotdot
dec ecx
add edx, 4
.nodotdot:
call sort
.skip:
mov [bSilentFolderMode], 0 ; leave silent mode
ret
 
highlight_init:
pushad
mov ebp, eax
lea esi, [ebp+40]
4256,35 → 5091,7
mov ah, [panel_selected_cursor_color]
mov [ebp+7], ah
.doname:
; call delete_last_dot
popad
.loopcont:
add eax, 304
dec ecx
jnz .ptrinit
.loopdone:
sub edi, [ebp + panel1_files - panel1_data]
shr edi, 2
mov [ebp + panel1_numfiles - panel1_data], edi
.done:
; ‘®àâ¨à®¢ª 
sort_files:
movzx eax, [ebp + panel1_sortmode - panel1_data]
mov ebx, [compare_fns + eax*4]
mov edx, [ebp + panel1_files - panel1_data]
mov ecx, [ebp + panel1_numfiles - panel1_data]
jecxz .skip
mov eax, [edx]
cmp word [eax+40], '..'
jnz .nodotdot
cmp byte [eax+42], 0
jnz .nodotdot
dec ecx
add edx, 4
.nodotdot:
call sort
.skip:
mov [bSilentFolderMode], 0 ; leave silent mode
ret
 
compare_name:
4689,7 → 5496,12
stc
ret
 
ReadFolder_default:
mov eax, 2
ret 10h
 
if 0
; Following subroutines work, but are slow
match_mask:
; in: esi->name, edi->mask
; out: CF clear <=> match
5273,7 → 6085,7
pop esi
ret
 
header db 'Kolibri Far 0.35',0
header db 'Kolibri Far ',version,0
 
nomem_draw db 'No memory for redraw.',0
.size = $ - nomem_draw
5703,6 → 6515,8
.OnKey dd ?
.keybar dd ?
.getname dd ?
.OnExit dd ?
.IsHandleUsed dd ?
end virtual
 
panels_vtable:
5710,6 → 6524,8
dd panels_OnKey
dd keybar_panels
dd panels_getname
dd panels_OnExit
dd panels_IsHandleUsed
 
viewer_vtable:
dd viewer_OnRedraw
5716,6 → 6532,8
dd viewer_OnKey
dd keybar_viewer
dd viewer_getname
dd viewer_OnExit
dd viewer_IsHandleUsed
 
; additions to this table require changes in tools.inc::get_error_msg
errors1:
6293,6 → 7111,7
ContinueBtn:
dd aContinue
 
aCannotOpenFile_ptr dd aCannotOpenFile
if lang eq ru
aDeleteCaption db '“¤ «¥­¨¥',0
aConfirmDeleteText db '‚ë å®â¨â¥ 㤠«¨âì',0
6354,6 → 7173,7
aDate db 4,'„ â '
aTime db 5,'∴•'
aCannotLoadDLL db '¥ ¬®£ã § £à㧨âì DLL',0
aCannotLoadPlugin db '¥ ¬®£ã § £à㧨âì ¯« £¨­',0
aInvalidDLL db '” ©« ­¥ ­ ©¤¥­ ¨«¨ ¨¬¥¥â ­¥¢¥à­ë© ä®à¬ â',0
aMissingExport db '¥®¡å®¤¨¬ ï äã­ªæ¨ï ­¥ ­ ©¤¥­ ',0
aInitFailed db 'Žè¨¡ª  ¯à¨ ¨­¨æ¨ «¨§ æ¨¨',0
6361,6 → 7181,8
aTables db '’ ¡«¨æë',0
aSelect db '®¬¥â¨âì',0
aDeselect db '‘­ïâì',0
aCannotOpenFile db 'Žè¨¡ª  ¯à¨ ®âªàë⨨ ä ©« ',0
aCannotSetFolder db '¥ ¬®£ã § ©â¨ ¢ ¯ ¯ªã',0
else
aDeleteCaption db 'Delete',0
aConfirmDeleteText db 'Do you wish to delete',0
6426,6 → 7248,7
aDate db 4,'Date'
aTime db 4,'Time'
aCannotLoadDLL db 'Cannot load DLL',0
aCannotLoadPlugin db 'Cannot load plugin',0
aInvalidDLL db 'File is not found or invalid',0
aMissingExport db 'Required function is not present',0
aInitFailed db 'Initialization failed',0
6433,11 → 7256,15
aTables db 'Tables',0
aSelect db 'Select',0
aDeselect db 'Deselect',0
aCannotOpenFile db 'Cannot open the file',0
aCannotSetFolder db 'Cannot enter to folder',0
end if
 
aOk db 'OK',0
aNoMemory db 'No memory!'
nullstr db 0
aUntitled db 'untitled',0
aDotDot db '..',0,0
standard_dll_path:
libini_name db '/sys/dll/'
standard_dll_path_size = $ - standard_dll_path
6447,13 → 7274,33
aVersion db 'version',0
aIniGetInt db 'ini.get_int',0
aIniGetStr db 'ini.get_str',0
aIniSetInt db 'ini.set_int',0
aIniEnumKeys db 'ini.enum_keys',0
aPluginLoad db 'plugin_load',0
aPluginUnload db 'plugin_unload',0
aGetattr db 'getattr',0
aOpen db 'open',0
aRead db 'read',0
aSetpos db 'setpos',0
aClose db 'close',0
aOpenFilePlugin db 'OpenFilePlugin',0
aClosePlugin db 'ClosePlugin',0
aReadFolder db 'ReadFolder',0
aSetFolder db 'SetFolder',0
aGetOpenPluginInfo db 'GetOpenPluginInfo',0
aGetPanelTitle db 'GetPanelTitle',0
aGetFiles db 'GetFiles',0
 
aConfirmations db 'Confirmations',0
aConfirmDelete db 'Delete',0
aConfirmDeleteIncomplete db 'DeleteIncomplete',0
 
aPanels db 'Panels',0
aLeftViewMode db 'LeftViewMode',0
aRightViewMode db 'RightViewMode',0
 
aAssociations db 'Associations',0
aPlugins db 'Plugins',0
aMenu db 'Menu',0
aFolderShortcuts db 'FolderShortcuts',0
aShortcut db 'Shortcut'
6464,9 → 7311,87
ini.get_int dd aIniGetInt
ini.get_str dd aIniGetStr
ini.enum_keys dd aIniEnumKeys
ini.set_int dd aIniSetInt
dd 0
 
plugin_exported:
dd aPluginUnload
dd aGetattr
dd aOpen
dd aRead
dd aSetpos
dd aClose
dd aOpenFilePlugin
dd aClosePlugin
dd aReadFolder
dd aSetFolder
dd aGetOpenPluginInfo
dd aGetPanelTitle
dd aGetFiles
dd 0
plugin_exported_default:
dd plugin_unload_default
dd getattr_default
dd open_default
dd read
dd setpos_default
dd close
dd OpenFilePlugin_default
dd ClosePlugin_default
dd ReadFolder_default
dd SetFolder_default
dd GetOpenPluginInfo_default
dd GetPanelTitle_default
dd GetFiles_default
 
kfar_info:
dd .size
dd version_dword
dd open
dd read
dd -1 ; write: to be implemented
dd seek
dd -1 ; flush: to be implemented
dd filesize
dd close
dd xpgalloc
dd xpgrealloc
dd pgfree
dd getfreemem
dd libini_alloc
dd libini_realloc
dd libini_free
dd menu
dd menu_centered_in
dd DialogBox
dd SayErr
dd Message
dd cur_width
.size = $ - kfar_info
 
plugins dd 0
num_plugins dd 0
alloc_plugins dd 0
 
virtual at 0
PluginInfo:
.unload dd ?
.getattr dd ?
.open dd ?
.read dd ?
.setpos dd ?
.close dd ?
.OpenFilePlugin dd ?
.ClosePlugin dd ?
.ReadFolder dd ?
.SetFolder dd ?
.GetOpenPluginInfo dd ?
.GetPanelTitle dd ?
.GetFiles dd ?
.size = $
end virtual
 
virtual at 0
PanelMode:
; up to 16 columns on one panel
.NumColumns dd ?
6592,6 → 7517,11
panel1_nfa dd ?
panel1_numfiles dd ?
panel1_files dd ?
panel1_hPlugin dd ?
panel1_hFile dd ?
panel1_parents dd ?
panel1_parents_sz dd ?
panel1_parents_alloc dd ?
panel1_colmode dd ?
panel1_colwidths rd 16+1
panel1_total_num dd ?
6598,6 → 7528,8
panel1_total_size dq ?
panel1_selected_num dd ?
panel1_selected_size dq ?
panel1_plugin_info:
panel1_plugin_flags dd ?
panel1_dir rb 1024
 
panel2_data:
6614,6 → 7546,11
panel2_nfa dd ?
panel2_numfiles dd ?
panel2_files dd ?
panel2_hPlugin dd ?
panel2_hFile dd ?
panel2_parents dd ?
panel2_parents_sz dd ?
panel2_parents_alloc dd ?
panel2_colmode dd ?
panel2_colwidths rd 16+1
panel2_total_num dd ?
6620,6 → 7557,8
panel2_total_size dq ?
panel2_selected_num dd ?
panel2_selected_size dq ?
panel2_plugin_info:
panel2_plugin_flags dd ?
panel2_dir rb 1024
 
;console_data rb max_width*max_height*2
6670,6 → 7609,10
active_screen_vtable dd ?
active_screen_data dd ?
 
default_attr dd ?
left_dotdot_entry rb 40+3 ; 40 bytes for attributes + '..'
right_dotdot_entry rb 40+3
 
aConfirmDeleteTextBuf rb aConfirmDeleteTextMax + 1
CopySourceTextBuf rb 512
CopyDestEditBuf rb 12+512+1
6686,6 → 7629,12
copy_buffer_size = 65536
copy_buffer rb copy_buffer_size
 
filedata_buffer_size = 1024
filedata_buffer rb filedata_buffer_size
 
source_hModule dd ?
source_hPlugin dd ?
source_hFile dd ?
; data for directory delete
; If directory nested level is >1024, then its full name is too big,
; so we see the overflow when creating full name (we check for this!)
6701,6 → 7650,7
del_bSkipAll db ? ; for directory errors
label copy_bSkipAll byte at del_bSkipAll
copy_bSkipAll2 db ? ; for file read/write errors
copy_bSkipAll3 db ? ; for SetFolder errors
 
bEndSlash db ?
bDestIsFolder db ?
6708,7 → 7658,7
 
; stack
align 4
rb 512
rb 32768
stacktop:
 
mem:
/programs/fs/kfar/trunk/kfar.ini
0,0 → 1,43
[Associations]
asm=/rd/1/TinyPad; AsmMenu1,AsmMenu2
inc=/rd/1/TinyPad
ini=/rd/1/TinyPad
txt=/rd/1/TinyPad
jpg=/rd/1/JpegView
jpeg=/rd/1/JpegView
gif=/rd/1/GIFVIEW; GifMenu1,MenuAnimage
wav=/rd/1/AC97SND
mp3=/rd/1/AC97SND
mid=/rd/1/MIDAMP
bmp=/rd/1/MV; BmpMenu1,MenuAnimage
png=/rd/1/@rcher
rtf=/rd/1/RtfRead
3ds=/rd/1/3d/view3ds
lif=/rd/1/demos/life2
skn=/rd/1/desktop
 
[Menu]
AsmMenu1=&¥¤ ªâ®à,/rd/1/TinyPad
AsmMenu2=&Š®¬¯¨«¨à®¢ âì,/rd/1/develop/fasm
GifMenu1=&à®á¬®âà,/rd/1/GIFVIEW
BmpMenu1=&à®á¬®âà,/rd/1/MV
MenuAnimage=&¥¤ ªâ®à,/rd/1/animage
 
[Panels]
LeftViewMode=2
RightViewMode=2
 
[FolderShortcuts]
# Œ®¦­® ®¯à¥¤¥«¨âì ¤® ¤¥áï⨠ááë«®ª ­  ¯ ¯ª¨ Shortcut0...Shortcut9,
# ­  â ª¨¥ ¯ ¯ª¨ ¬®¦­® ᤥ« âì ¡ëáâàë© ¯¥à¥å®¤ ¯® RCtrl+<æ¨äà >
Shortcut0=/rd/1
 
[Confirmations]
Delete=1
DeleteIncomplete=0
 
# ‘«¥¢  ®â §­ ª  à ¢¥­á⢠ ¬®¦­® áâ ¢¨âì «î¡®¥ ®á¬ëá«¥­­®¥ ¨«¨ ¡¥áá¬ëá«¥­­®¥
# ¨¬ï; á¯à ¢  - ¯ãâì ª ¯« £¨­ã.
# …᫨ ¯ãâì ­¥  ¡á®«î⥭, â® ®­ ®âáç¨â뢠¥âáï ®â ¯ ¯ª¨ á ¡¨­ à­¨ª®¬ kfar.
[Plugins]
ArchiveReader=kfar_arc.obj
/programs/fs/kfar/trunk/kfar_arc/7z.inc
0,0 → 1,3138
; Loading of 7z archives was ported from 7z sources (file 7zip\Archive\7z\7zIn.cpp).
; The version 7-Zip 4.42 was used.
; 7-Zip is copyright (C) 1999-2006 Igor Pavlov.
; Assembler version as KFar plugin has been written by diamond, 2007.
 
virtual at 0
file_in_7z:
.fullname dd ? ; pointer to cp866 string
.name dd ?
.namelen dd ?
.bIsDirectory db ?
.bPseudoFolder db ?
rb 2
.parent dd ? ; pointer to parent directory record
.subfolders dd ? ; head of L2-list of subfolders [for folders]
.subfolders.end dd ?
.subfiles dd ? ; head of L2-list of files [for folders]
.subfiles.end dd ?
.NumSubItems dd ?
.next dd ? ; next item of list of subfolders or files
.prev dd ? ; previous item of list of subfolders or files
.attr dd ?
.FileCRC dd ?
.startPos dq ?
.CreationTime dq ?
.LastAccessTime dq ?
.LastWriteTime dq ?
.UnPackSize dq ?
.folder dd ?
.folder_index dd ?
.folderStart dq ?
.bAttrDefined db ?
.bStartPosDefined db ?
.bCRCDefined db ?
.bCreationTimeDefined db ?
.bLastAccessTimeDefined db ?
.bLastWriteTimeDefined db ?
.bHasStream db ?
.bAnti db ?
.stamp dd ?
.size = $
end virtual
 
virtual at 0
handle_7z:
.type dd ?
.root.subfolders dd ?
.root.subfolders.end dd ?
.root.subfiles dd ?
.root.subfiles.end dd ?
.root.NumSubItems dd ?
.curdir dd ?
.NumFiles dd ?
.names_buf dd ?
.host dd ?
.host_datetime rd 6
; streams info
.numPackStreams dd ?
.packSizes dd ?
.numFolders dd ?
.unpackCRCsDefined dd ?
.unpackCRCs dd ?
.folders dd ?
.last_folder dd ?
.last_pos dq ?
.last_context dd ?
.last_main_stream dd ?
.password_len dd ? ; -1 if no password defined; in characters
.password rw password_maxlen
.basesize = $
; .size = .basesize + .NumFiles * file_in_7z.size
end virtual
 
iglobal
align 4
empty_7z_handle:
dd type_7z
dd 0,0,0,0,0,0
endg
 
kEnd = 0
kHeader = 1
kArchiveProperties = 2
kAdditionalStreamsInfo = 3
kMainStreamsInfo = 4
kFilesInfo = 5
kPackInfo = 6
kUnPackInfo = 7
kSubStreamsInfo = 8
kSize = 9
kCRC = 10
kFolder = 11
kCodersUnPackSize = 12
kNumUnPackStream = 13
kEmptyStream = 14
kEmptyFile = 15
kAnti = 16
kName = 17
kCreationTime = 18
kLastAccessTime = 19
kLastWriteTime = 20
kWinAttributes = 21
kComment = 22
kEncodedHeader = 23
kStartPos = 24
 
_7z.ReadByte:
cmp edi, [bufend]
jae return.err
mov al, [edi]
inc edi
ret
_7z.ReadWord:
add edi, 2
cmp edi, [bufend]
ja return.err
mov ax, [edi-2]
ret
_7z.ReadDword:
add edi, 4
cmp edi, [bufend]
ja return.err
mov eax, [edi-4]
ret
 
_7z.SkipSize:
test edx, edx
jnz return.err
add edi, eax
jc return.err
cmp edi, [bufend]
ja return.err
ret
 
_7z.ReadNumber:
xor eax, eax
push eax
push eax
call _7z.ReadByte
push ecx
xor ecx, ecx
@@:
add al, al
jnc @f
inc ecx
jmp @b
@@:
shr eax, cl
shr eax, 1
jz @f
mov [esp+4+ecx], al
@@:
jecxz .ret
push edx
xor edx, edx
@@:
call _7z.ReadByte
mov [esp+8+edx], al
inc edx
loop @b
pop edx
.ret:
pop ecx
pop eax
pop edx
ret
 
_7z.ReadNum:
push edx
call _7z.ReadNumber
test edx, edx
jnz return.err
test eax, eax
js return.err
pop edx
ret
 
open_7z:
; CInArchive::ReadDatabase()
cmp byte [esi+6], 0 ; major version must be 0
; minor version does not be checked ([byte +7]=2 for now)
jz @f
xor eax, eax
ret
@@:
and [hOut], 0
and [_7z.FreeSubStreams], 0
and [_7z.tmpVector], 0
push esi
add esi, 12
mov ecx, 20
call crc
pop esi
cmp eax, [esi+8]
jnz .header_crc_error
cmp dword [esi+24], 0
jnz .header_error
mov edi, buffer
mov ecx, [esi+20]
mov [bufsize], ecx
test ecx, ecx
jnz .notempty
mov eax, empty_7z_handle
push ebp
call [close]
ret
.notempty:
cmp ecx, 1024
jbe @f
call [pgalloc]
test eax, eax
jz .reterr
mov edi, eax
@@:
mov [bufptr], edi
lea eax, [edi+ecx]
mov [bufend], eax
mov eax, [esi+12]
mov edx, [esi+16]
add eax, 20h ; end of main header
adc edx, 0
push edx
push eax
push 0
push ebp
call [seek]
push ecx
push edi
push ebp
call [read]
cmp eax, ecx
jnz .header_error
push esi
mov esi, edi
call crc
pop esi
cmp eax, [esi+28]
jz .header_ok
.header_crc_error:
.header_error:
push ContinueBtn
push 1
push HeaderError_ptr
push 1
call [SayErr]
.clear:
mov ecx, [_7z.tmpVector]
jecxz @f
call [pgfree]
@@:
mov ecx, [hOut]
jecxz @f
call _7z.CloseHandle
@@:
mov ebx, [_7z.dataVectorSize]
test ebx, ebx
jz @f
call _7z.ReadAndDecodePackedStreams.free2
@@:
mov ecx, [_7z.FreeSubStreams]
jecxz @f
call [pgfree]
@@:
mov ecx, [bufptr]
cmp ecx, buffer
jz .reterr
call [pgfree]
.reterr:
or eax, -1
ret
.header_ok:
mov [_esp], esp
mov [inStream], ebp
.loop:
mov [error_proc], .header_error
mov [clear_proc], .clear
and [_7z.dataVectorSize], 0
call _7z.ReadNum
cmp eax, kHeader
jz .found_header
cmp eax, kEncodedHeader
jnz .header_error
call _7z.ReadAndDecodePackedStreams
cmp [_7z.StreamsInfo.numFolders], 0
jz .free_empty
cmp [_7z.StreamsInfo.numFolders], 1
jnz return.err
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
@@:
mov edi, [_7z.unpbuf+4]
mov [bufptr], edi
mov ecx, [_7z.unpbuf]
add ecx, edi
mov [bufend], ecx
mov [error_proc], .header_error
mov [clear_proc], .clear
and [_7z.dataVectorSize], 0
call _7z.ReadNum
cmp eax, kHeader
jz .found_header
jmp return.err
.free_empty:
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
@@:
push [inStream]
call [close]
mov eax, empty_7z_handle
ret
.found_header:
call _7z.ReadNum
cmp eax, kArchiveProperties
jnz .no_archive_props
@@:
call _7z.ReadNum
test eax, eax
jz @f
call _7z.SkipData
jmp @b
@@:
call _7z.ReadNum
.no_archive_props:
cmp eax, kAdditionalStreamsInfo
jnz .no_additional_streams
call _7z.ReadAndDecodePackedStreams
mov eax, [_7z.unpacked]
mov [_7z.dataVector], eax
mov eax, [_7z.StreamsInfo.numFolders]
mov [_7z.dataVectorSize], eax
mov [error_proc], .header_error
mov [clear_proc], .clear
call _7z.ReadNum
.no_additional_streams:
cmp eax, kMainStreamsInfo
jnz return.err
call _7z.ReadStreamsInfo
call _7z.ReadNum
test eax, eax
jnz .notempty2
.empty2:
mov ebx, [_7z.dataVectorSize]
test ebx, ebx
jz @f
call _7z.ReadAndDecodePackedStreams.free2
@@:
mov ecx, [_7z.FreeSubStreams]
jecxz @f
call [pgfree]
@@:
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
@@:
push [inStream]
call [close]
mov eax, empty_7z_handle
ret
.notempty2:
cmp eax, kFilesInfo
jnz return.err
call _7z.ReadNum
test eax, eax
jz .empty2
mov ebx, eax ; number of files in archive
imul ecx, ebx, file_in_7z.size
add ecx, handle_7z.basesize
mov [hOut.allocated], ecx
call [pgalloc]
test eax, eax
jz return.clear
mov [hOut], eax
mov [eax+handle_7z.type], type_7z
mov [eax+handle_7z.NumFiles], ebx
push edi
lea edi, [eax+handle_7z.numPackStreams]
mov esi, _7z.StreamsInfo
mov ecx, 6
rep movsd
or [eax+handle_7z.password_len], -1
or [eax+handle_7z.last_folder], -1
mov [eax+handle_7z.last_context], ecx
mov [eax+handle_7z.names_buf], ecx
mov [eax+handle_7z.host], ecx
cmp [bPasswordDefined], cl
jz @f
mov ecx, [password_size]
mov [eax+handle_7z.password_len], ecx
lea edi, [eax+handle_7z.password]
mov esi, password_unicode
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
@@:
lea edi, [eax+handle_7z.basesize]
imul ecx, ebx, file_in_7z.size/4
xor eax, eax
rep stosd
pop edi
mov eax, [_7z.StreamsInfo.SubStreamsSizes]
mov [_7z.FreeSubStreams], eax
mov [error_proc], .header_error
mov [clear_proc], .clear
mov ecx, ebx
shl ecx, 2
call [pgalloc]
test eax, eax
jz return.clear
push edi
mov edi, eax
mov [_7z.tmpVector], eax
add eax, ebx
mov [_7z.emptyStreams], eax
add eax, ebx
mov [_7z.emptyFiles], eax
add eax, ebx
mov [_7z.antiFiles], eax
mov ecx, ebx
xor eax, eax
rep stosd
pop edi
mov [_7z.numEmptyStreams], eax
.parse_header:
call _7z.ReadNum
test eax, eax
jz .parse_header_done
mov ecx, eax ; ecx = type
call _7z.ReadNum ; eax = size
cmp ecx, kName
jz .parse_names
cmp ecx, kWinAttributes
jz .parse_winAttr
cmp ecx, kStartPos
jz .parse_startPos
cmp ecx, kEmptyStream
jz .parse_emptyStream
cmp ecx, kEmptyFile
jz .parse_emptyFile
cmp ecx, kAnti
jz .parse_anti
cmp ecx, kCreationTime
jz .parse_time
cmp ecx, kLastWriteTime
jz .parse_time
cmp ecx, kLastAccessTime
jz .parse_time
xor edx, edx
call _7z.SkipSize
jmp .parse_header
.parse_names:
push eax
call _7z.SwitchStream
pop eax
jz @f
mov eax, [bufend]
sub eax, edi
@@:
shr eax, 1 ; size of ANSI string is a half of size of UNICODE string
mov ecx, eax
call [pgalloc]
test eax, eax
jz return.clear
mov ebp, eax
mov esi, [hOut]
mov [esi+handle_7z.names_buf], eax
add eax, ecx
push eax ; remember limit
mov ecx, ebx
add esi, handle_7z.basesize + file_in_7z.fullname
mov [bWasWarning], 0
.parse_names_loop:
mov [esi], ebp
add esi, file_in_7z.size
.parse_names_loop_int:
cmp ebp, [esp]
jae return.err
call _7z.ReadWord
; UNICODE char -> cp866 char
cmp ax, 0x80
jb .id
cmp ax, 0x401
jz .yo1
cmp ax, 0x451
jz .yo2
cmp ax, 0x410
jb .unk
cmp ax, 0x440
jb .rus1
cmp ax, 0x450
jb .rus2
.unk:
cmp [bWasWarning], 0
jnz @f
push ContinueBtn
push 1
push aEncodingProblem_str_ptr
push 3
push aEncodingProblem
call [Message]
inc [bWasWarning]
@@:
mov al, '_'
jmp .id
.yo1:
mov al, 'ð'
jmp .id
.yo2:
mov al, 'ñ'
jmp .id
.rus1:
; 0x410-0x43F -> 0x80-0xAF
add al, 0x70
jmp .id
.rus2:
; 0x440-0x44F -> 0xE0-0xEF
add al, 0xA0
.id:
mov [ebp], al
inc ebp
test al, al
jnz .parse_names_loop_int
loop .parse_names_loop
pop eax
call _7z.UnswitchStream
jmp .parse_header
.parse_winAttr:
mov edx, [_7z.tmpVector]
push ebx
mov ecx, ebx
mov ebx, edx
call _7z.ReadBoolVector2
pop ebx
call _7z.SwitchStream
mov esi, [hOut]
add esi, handle_7z.basesize
mov ecx, ebx
.winAttrLoop:
mov al, [edx]
inc edx
mov [esi+file_in_7z.bAttrDefined], al
test al, al
jz @f
call _7z.ReadDword
mov [esi+file_in_7z.attr], eax
@@:
add esi, file_in_7z.size
loop .winAttrLoop
call _7z.UnswitchStream
jmp .parse_header
.parse_startPos:
mov edx, [_7z.tmpVector]
push ebx
mov ecx, ebx
mov ebx, edx
call _7z.ReadBoolVector2
pop ebx
call _7z.SwitchStream
mov esi, [hOut]
add esi, handle_7z.basesize
mov ecx, ebx
.startPosLoop:
mov al, [edx]
inc edx
mov [esi+file_in_7z.bStartPosDefined], al
test al, al
jz @f
call _7z.ReadDword
mov dword [esi+file_in_7z.startPos], eax
call _7z.ReadDword
mov dword [esi+file_in_7z.startPos+4], eax
@@:
add esi, file_in_7z.size
loop .startPosLoop
call _7z.UnswitchStream
jmp .parse_header
.parse_emptyStream:
mov edx, [_7z.emptyStreams]
push ebx
mov ecx, ebx
mov ebx, edx
call _7z.ReadBoolVector
pop ebx
and [_7z.numEmptyStreams], 0
mov ecx, ebx
.emptyStrLoop:
cmp byte [edx], 0
jz @f
inc [_7z.numEmptyStreams]
@@:
inc edx
loop .emptyStrLoop
jmp .parse_header
.parse_emptyFile:
push ebx
mov ecx, [_7z.numEmptyStreams]
mov ebx, [_7z.emptyFiles]
call _7z.ReadBoolVector
pop ebx
jmp .parse_header
.parse_anti:
push ebx
mov ecx, [_7z.numEmptyStreams]
mov ebx, [_7z.antiFiles]
call _7z.ReadBoolVector
pop ebx
jmp .parse_header
.parse_time:
push ecx
push ebx
mov ecx, ebx
mov ebx, [_7z.tmpVector]
call _7z.ReadBoolVector2
pop ebx
call _7z.SwitchStream
mov esi, [hOut]
add esi, handle_7z.basesize
xor ecx, ecx
.timeLoop:
mov eax, [_7z.tmpVector]
mov al, [eax+ecx]
pop edx
push edx
mov [esi + file_in_7z.bCreationTimeDefined + edx - kCreationTime], al
test al, al
jz @f
call _7z.ReadDword
push eax
call _7z.ReadDword
mov edx, eax
pop eax
push edi
mov edi, [esp+4]
lea edi, [esi + file_in_7z.CreationTime + (edi-kCreationTime)*8]
call ntfs_datetime_to_bdfe
pop edi
@@:
add esi, file_in_7z.size
inc ecx
cmp ecx, ebx
jb .timeLoop
call _7z.UnswitchStream
pop eax
jmp .parse_header
.parse_header_done:
xor ecx, ecx ; index in emptyFiles
xor edx, edx ; index in subStreams
xor ebp, ebp ; index in files
mov esi, [hOut]
add esi, handle_7z.basesize
.filesLoop:
mov eax, [_7z.emptyStreams]
mov al, [eax+ebp]
xor al, 1
mov [esi+file_in_7z.bHasStream], al
jz .nostream
mov [esi+file_in_7z.bIsDirectory], 0
mov [esi+file_in_7z.bAnti], 0
mov eax, [_7z.StreamsInfo.SubStreamsSizes]
push dword [eax+edx*8]
pop dword [esi+file_in_7z.UnPackSize]
push dword [eax+edx*8+4]
pop dword [esi+file_in_7z.UnPackSize+4]
mov eax, [_7z.StreamsInfo.SubStreamsCRCsDefined]
mov al, [eax+edx]
mov [esi+file_in_7z.bCRCDefined], al
test al, al
jz @f
mov eax, [_7z.StreamsInfo.SubStreamsCRCs]
mov eax, [eax+edx*4]
mov [esi+file_in_7z.FileCRC], eax
@@:
inc edx
jmp .filesCont
.nostream:
mov eax, [_7z.emptyFiles]
cmp byte [eax+ecx], 0
setz [esi+file_in_7z.bIsDirectory]
mov eax, [_7z.antiFiles]
cmp byte [eax+ecx], 0
setnz [esi+file_in_7z.bAnti]
and dword [esi+file_in_7z.UnPackSize], 0
and dword [esi+file_in_7z.UnPackSize+4], 0
mov [esi+file_in_7z.bCRCDefined], 0
inc ecx
.filesCont:
inc ebp
add esi, file_in_7z.size
dec ebx
jnz .filesLoop
mov ecx, [_7z.tmpVector]
call [pgfree]
and [_7z.tmpVector], 0
mov ebx, [_7z.dataVectorSize]
test ebx, ebx
jz @f
call _7z.ReadAndDecodePackedStreams.free2
and [_7z.dataVectorSize], 0
@@:
mov ecx, [_7z.FreeSubStreams]
jecxz @f
call [pgfree]
and [_7z.FreeSubStreams], 0
@@:
mov ecx, [bufptr]
cmp ecx, buffer
jz @f
call [pgfree]
mov [bufptr], buffer
@@:
xor esi, esi ; index of folder
mov edi, [hOut]
mov ebx, [edi+handle_7z.NumFiles]
add edi, handle_7z.basesize ; pointer to fileinfo
push 0 ; start index of packed stream for folder
.getfoldersloop0:
xor edx, edx ; index in folder
push edx edx ; position in folder
.getfoldersloop:
dec ebx
js .getfoldersdone
cmp [edi+file_in_7z.bHasStream], 0
jnz @f
test edx, edx
jz .nofolder
@@:
test edx, edx
jnz .notfirst
; skip empty folders
@@:
mov eax, [hOut]
cmp esi, [eax+handle_7z.numFolders]
jae return.err
mov eax, [eax+handle_7z.folders]
mov eax, [eax+esi*4]
cmp edx, [eax+_7z.StreamsInfo.numUnPackStreams]
jb @f
inc esi
jmp @b
@@:
.notfirst:
mov [edi+file_in_7z.folder], esi
mov [edi+file_in_7z.folder_index], edx
mov eax, [esp]
mov dword [edi+file_in_7z.folderStart], eax
mov eax, [esp+4]
mov dword [edi+file_in_7z.folderStart+4], eax
mov ecx, dword [edi+file_in_7z.UnPackSize]
add [esp], ecx
mov ecx, dword [edi+file_in_7z.UnPackSize+4]
adc [esp+4], ecx
add edi, file_in_7z.size
inc edx
mov eax, [hOut]
mov eax, [eax+handle_7z.folders]
mov eax, [eax+esi*4]
cmp edx, [eax+_7z.StreamsInfo.numUnPackStreams]
jb .getfoldersloop
inc esi
pop edx edx
jmp .getfoldersloop0
.nofolder:
push -1
pop eax
mov [edi+file_in_7z.folder], eax
mov [edi+file_in_7z.folder_index], eax
mov dword [edi+file_in_7z.folderStart], eax
mov dword [edi+file_in_7z.folderStart+4], eax
add edi, file_in_7z.size
jmp .getfoldersloop
.getfoldersdone:
pop eax eax eax
mov ebp, [hOut]
mov esi, [ebp+handle_7z.folders]
xor ebx, ebx
cmp ebx, [ebp+handle_7z.numFolders]
jae .getoffsdone
.getoffsloop:
lodsd
test ebx, ebx
jnz .getoffs2
mov edx, dword [_7z.StreamsInfo.dataOffset]
mov dword [eax+_7z.StreamsInfo.packOffset], edx
mov edx, dword [_7z.StreamsInfo.dataOffset+4]
mov dword [eax+_7z.StreamsInfo.packOffset+4], edx
jmp .getoffscont
.getoffs2:
mov ecx, [esi-8]
mov edx, dword [ecx+_7z.StreamsInfo.packOffset]
mov dword [eax+_7z.StreamsInfo.packOffset], edx
mov edx, dword [ecx+_7z.StreamsInfo.packOffset+4]
mov dword [eax+_7z.StreamsInfo.packOffset+4], edx
mov edi, [ecx+_7z.StreamsInfo.startPackedStream]
mov ecx, [ecx+_7z.StreamsInfo.numPackedStreams]
push ecx
add ecx, edi
cmp ecx, [ebp+handle_7z.numPackStreams]
ja return.err
pop ecx
shl edi, 3
add edi, [ebp+handle_7z.packSizes]
@@:
dec ecx
js @f
mov edx, [edi]
add dword [eax+_7z.StreamsInfo.packOffset], edx
mov edx, [edi+4]
adc dword [eax+_7z.StreamsInfo.packOffset+4], edx
add edi, 8
jmp @b
@@:
.getoffscont:
inc ebx
cmp ebx, [ebp+handle_7z.numFolders]
jb .getoffsloop
.getoffsdone:
mov edx, [hOut]
mov ebx, [edx+handle_7z.NumFiles]
lea edi, [edx+handle_7z.root.subfolders]
add edx, handle_7z.basesize
push file_in_7z.size
call init_file_links
mov eax, [hOut]
and [eax+handle_7z.curdir], 0 ; set root directory
mov esi, [inStream]
mov [eax+handle_7z.host], esi
lea edi, [eax+handle_7z.host_datetime]
mov esi, [esp+16]
add esi, 8
mov ecx, 6
rep movsd
ret
 
_7z.CloseHandle:
mov esi, ecx
push [esi+handle_7z.host]
call [close]
mov ecx, [esi+handle_7z.packSizes]
call [pgfree]
mov ecx, [esi+handle_7z.folders]
call [pgfree]
mov ecx, [esi+handle_7z.names_buf]
call [pgfree]
mov ecx, [esi+handle_7z.last_context]
jecxz @f
call [pgfree]
@@:
mov ecx, esi
call [pgfree]
ret
 
close_7z:
mov ecx, [esp+4]
cmp ecx, empty_7z_handle
jz @f
call _7z.CloseHandle
@@:
ret 4
 
uglobal
align 4
_7z.unpacked dd ?
_7z.unpbuf rd 2*8
_7z.CurInStream dd ?
_7z.dataVector dd ?
_7z.dataVectorSize dd ?
_7z.FreeSubStreams dd ?
_7z.tmpVector dd ?
_7z.emptyStreams dd ?
_7z.numEmptyStreams dd ?
_7z.emptyFiles dd ?
_7z.antiFiles dd ?
endg
 
_7z.ReadAndDecodePackedStreams:
call _7z.ReadStreamsInfo
mov ecx, [_7z.StreamsInfo.numFolders]
test ecx, ecx
jz .ret2
push ecx
mov ecx, [_7z.StreamsInfo.SubStreamsSizes]
jecxz @f
call [pgfree]
and [_7z.StreamsInfo.SubStreamsSizes], 0
@@:
pop ecx
mov eax, _7z.unpbuf
cmp ecx, 8
jbe .1
shl ecx, 3
call [pgalloc]
test eax, eax
jz return.clear
mov esi, eax
@@:
and dword [esi], 0
add esi, 4
sub ecx, 4
jnz @b
.1:
mov [_7z.unpacked], eax
mov esi, eax
xor ecx, ecx
mov [_7z.CurInStream], ecx
mov [error_proc], .error
mov [clear_proc], .clear
.loop:
mov eax, [_7z.StreamsInfo.folders]
mov ebx, [eax+ecx*4]
call _7z.GetUnPackSize
test edx, edx
jnz return.err
test eax, eax
js return.err
push ecx
mov [esi], eax
mov [_7z.decode.outBufferSize], eax
mov ecx, eax
call [pgalloc]
test eax, eax
jz return.err
mov [esi+4], eax
mov [_7z.decode.outBufferPtr], eax
push esi
call _7z.decode
pop esi
pop ecx
push ecx
mov eax, [_7z.StreamsInfo.unpackCRCsDefined]
cmp byte [eax+ecx], 0
jz @f
push esi
mov ecx, [esi]
mov esi, [esi+4]
call crc
pop esi
pop ecx
push ecx
mov edx, [_7z.StreamsInfo.unpackCRCs]
cmp [edx+ecx*4], eax
jnz return.err
@@:
add esi, 8
pop ecx
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .loop
.ret:
mov ecx, [_7z.StreamsInfo.folders]
call [pgfree]
mov [error_proc], .error2
mov [clear_proc], .clear2
.ret2:
mov ecx, [_7z.StreamsInfo.packSizes]
call [pgfree]
ret
 
.error:
call .free
jmp _7z.ReadStreamsInfo.error
.clear:
call .free
jmp _7z.ReadStreamsInfo.clear
.error2:
call .free
jmp open_7z.header_error
.clear2:
call .free
jmp open_7z.clear
.free:
mov ebx, [_7z.StreamsInfo.numFolders]
.free2:
dec ebx
js @f
mov ecx, [_7z.unpacked]
mov ecx, [ecx+ebx*8+4]
call [pgfree]
jmp .free2
@@:
mov ecx, [_7z.unpacked]
cmp ecx, _7z.unpbuf
jz @f
call [pgfree]
@@:
ret
 
_7z.GetUnPackSize:
xor edx, edx
mov eax, [ebx+_7z.StreamsInfo.numOutStreams]
test eax, eax
jz .ret
.scan:
dec eax
js return.err
push ecx
mov ecx, [ebx+_7z.StreamsInfo.numBindPairs]
mov edx, [ebx+_7z.StreamsInfo.bindPairs]
@@:
add edx, 8
dec ecx
js .found
cmp [edx-4], eax
jnz @b
pop ecx
jmp .scan
.found:
mov [ebx+_7z.StreamsInfo.mainOutStream], eax
mov ecx, [ebx+_7z.StreamsInfo.unpackSizes]
mov edx, [ecx+eax*8+4]
mov eax, [ecx+eax*8]
pop ecx
.ret:
ret
 
uglobal
align 4
_7z.StreamsInfo:
.numPackStreams dd ?
.packSizes dd ? ; 8 bytes per item
.numFolders dd ?
.unpackCRCsDefined dd ?
.unpackCRCs dd ?
.folders dd ?
.folders.size dd ?
.folders.alloc dd ?
.dataOffset dq ?
.packCRCsDefined dd ? ; 1 byte per item
.packCRCs dd ? ; 4 bytes per item
virtual at 0
.numCoders dd ?
.bindPairs dd ?
.numBindPairs dd ?
.packedStreams dd ?
.numPackedStreams dd ?
.startPackedStream dd ?
.numOutStreams dd ?
.unpackSizes dd ?
.mainOutStream dd ?
.numUnPackStreams dd ?
.packOffset dq ?
.fsz = $
end virtual
.numSubStreams dd ?
.SubStreamsSizes dd ?
.SubStreamsCRCsDefined dd ?
.SubStreamsCRCs dd ?
.tmpSubStreamsCRCsDefined dd ?
.tmpSubStreamsCRCs dd ?
endg
 
_7z.SkipData:
call _7z.ReadNumber
call _7z.SkipSize
ret
 
_7z.WaitAttribute:
call _7z.ReadNumber
cmp eax, ecx
jz @f
test eax, eax
jz return.err
call _7z.SkipData
jmp _7z.WaitAttribute
@@:
ret
 
_7z.ReadBoolVector2:
; in: ebx->vector, ecx=size
call _7z.ReadByte
test al, al
jz _7z.ReadBoolVector
push ebx ecx
jecxz .ret
@@:
mov byte [ebx], 1
inc ebx
loop @b
.ret:
pop ecx ebx
ret
 
_7z.ReadBoolVector:
push ebx ecx
jecxz .ret
xor eax, eax
.1:
add al, al
jnz @f
call _7z.ReadByte
stc
adc al, al
@@:
setc byte [ebx]
inc ebx
loop .1
.ret:
pop ecx ebx
ret
 
_7z.ReadHashDigests:
; in: ebx->bool vector, esi->crc, ecx=size
call _7z.ReadBoolVector2
jecxz .ret
.1:
xor eax, eax
cmp byte [ebx], al
jz @f
call _7z.ReadDword
@@:
mov [esi], eax
add esi, 4
inc ebx
loop .1
.ret:
ret
 
uglobal
_7z.saved_edi dd ?
_7z.saved_edi_end dd ?
endg
 
_7z.SwitchStream:
mov eax, [bufend]
mov [_7z.saved_edi_end], eax
call _7z.ReadByte
test al, al
jnz @f
ret
@@:
call _7z.ReadNum
mov [_7z.saved_edi], edi
cmp eax, [_7z.dataVectorSize]
jae return.err
shl eax, 3
add eax, [_7z.dataVector]
mov edi, [eax+4]
mov eax, [eax]
add eax, edi
mov [bufend], eax
ret
 
_7z.UnswitchStream:
mov eax, [_7z.saved_edi_end]
cmp eax, [bufend]
jnz @f
ret
@@:
mov [bufend], eax
mov edi, [_7z.saved_edi]
@@:
ret
 
; 6 ¯à®£à ¬¬¨á⮢ ¯ëâ «¨áì ª®¤ ¯®­ïâì,
; Ž¤¨­ ¨§ ­¨å á®èñ« á 㬠, ¨ ¨å ®áâ «®áì 5.
 
_7z.ReadStreamsInfo:
xor eax, eax
mov [_7z.StreamsInfo.numPackStreams], eax
mov [_7z.StreamsInfo.packSizes], eax
mov [_7z.StreamsInfo.numFolders], eax
mov [_7z.StreamsInfo.folders], eax
mov [_7z.StreamsInfo.numSubStreams], eax
mov [_7z.StreamsInfo.SubStreamsSizes], eax
mov [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax
mov [error_proc], .error
mov [clear_proc], .clear
.mainloop:
call _7z.ReadNum
test eax, eax
jz @b
cmp eax, kSubStreamsInfo
jz .SubStreamsInfo
cmp eax, kUnPackInfo
jz .UnpackInfo
cmp eax, kPackInfo
jnz return.err
 
.PackInfo:
cmp [_7z.StreamsInfo.numPackStreams], 0
jnz return.err
call _7z.ReadNumber
add eax, 0x20
adc edx, 0
mov dword [_7z.StreamsInfo.dataOffset], eax
mov dword [_7z.StreamsInfo.dataOffset+4], edx
call _7z.ReadNum
mov [_7z.StreamsInfo.numPackStreams], eax
mov ecx, kSize
call _7z.WaitAttribute
mov ecx, [_7z.StreamsInfo.numPackStreams]
imul ecx, 8+1+4
jecxz .nostreams1
call [pgalloc]
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.packSizes], eax
mov ecx, [_7z.StreamsInfo.numPackStreams]
push eax
lea eax, [eax+ecx*8]
mov [_7z.StreamsInfo.packCRCsDefined], eax
mov ebx, eax
add eax, ecx
mov [_7z.StreamsInfo.packCRCs], eax
@@:
mov byte [ebx], 0
inc ebx
loop @b
pop eax
.nostreams1:
mov ecx, [_7z.StreamsInfo.numPackStreams]
jecxz .noloop1
mov esi, eax
@@:
call _7z.ReadNumber
mov [esi], eax
mov [esi+4], edx
add esi, 8
loop @b
.noloop1:
call _7z.ReadNum
test eax, eax
jz .mainloop
cmp eax, kCRC
jz .packInfo.crc
call _7z.SkipData
jmp .noloop1
.packInfo.crc:
mov esi, [_7z.StreamsInfo.packCRCs]
mov ebx, [_7z.StreamsInfo.packCRCsDefined]
mov ecx, [_7z.StreamsInfo.numPackStreams]
call _7z.ReadHashDigests
jmp .noloop1
 
.UnpackInfo:
cmp [_7z.StreamsInfo.folders], 0
jnz return.err
mov ecx, kFolder
call _7z.WaitAttribute
call _7z.ReadNum
mov ecx, eax
mov [_7z.StreamsInfo.numFolders], eax
call _7z.SwitchStream
test ecx, ecx
jz .nofolders
push ecx
mov ecx, 0x1000
and [_7z.StreamsInfo.folders.size], 0
mov [_7z.StreamsInfo.folders.alloc], ecx
call [pgalloc]
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.folders], eax
pop ecx
lea ecx, [ecx*9]
call .folders_alloc
xor ecx, ecx
.folderloop:
mov eax, [_7z.StreamsInfo.folders]
push [_7z.StreamsInfo.folders.size]
pop dword [eax+ecx*4]
push ebp
mov [_ebp], ebp
push ecx
mov ecx, _7z.StreamsInfo.fsz
call .folders_alloc
mov ebp, eax
add ebp, [_7z.StreamsInfo.folders]
call _7z.ReadNum
mov [ebp+_7z.StreamsInfo.numCoders], eax
test eax, eax
jz return.err
mov ecx, eax
push ecx
shl ecx, 2
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
pop ecx
add eax, [_7z.StreamsInfo.folders]
@@:
and dword [eax], 0
add eax, 4
loop @b
push 0 ; numOutStreams
push 0 ; numInStreams
; [folders] = array of pointers to coders info
; Format of coder info:
; dd NextCoder
; db MethodID.IDSize
; times IDSize db MethodID.ID
; dd NumInStreams
; dd NumOutStreams
; dd PropSize
; times PropSize db Properties
xor esi, esi
.coders_loop:
call _7z.ReadByte
mov dl, al
and eax, 0xF
lea ecx, [eax+17]
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
push eax
mov ecx, [_7z.StreamsInfo.folders]
lea ebx, [ebp+esi*4+_7z.StreamsInfo.fsz]
@@:
cmp dword [ebx], 0
jz @f
mov ebx, [ebx]
add ebx, ecx
jmp @b
@@:
mov [ebx], eax
pop ebx
add ebx, ecx
and dword [ebx], 0
add ebx, 4
mov ecx, edx
and ecx, 0xF
mov byte [ebx], cl
inc ebx
jecxz .2
@@:
call _7z.ReadByte
mov byte [ebx], al
inc ebx
loop @b
.2:
test dl, 10h
jnz .coder_multiple_streams
mov dword [ebx], 1
mov dword [ebx+4], 1
inc dword [esp]
inc dword [esp+4]
jmp @f
.coder_multiple_streams:
call _7z.ReadNum
mov [ebx], eax
add dword [esp], eax
call _7z.ReadNum
mov [ebx+4], eax
add dword [esp+4], eax
; all currently defined 7z coders have 1 unpacked stream
; moreover, all reasonable coders have 1 unpacked stream
; so assume 1 output stream for unpacker - this simplifies decoding procedure
cmp eax, 1
jnz return.err
@@:
and dword [ebx+8], 0
add ebx, 12
test dl, 20h
jz .coder_no_properties
call _7z.ReadNum
test eax, eax
jz .coder_no_properties
mov [ebx-4], eax
mov ecx, eax
sub ebx, [_7z.StreamsInfo.folders]
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
add ebx, [_7z.StreamsInfo.folders]
@@:
call _7z.ReadByte
mov [ebx], al
inc ebx
loop @b
.coder_no_properties:
test dl, dl
js .coders_loop
inc esi
cmp esi, [ebp+_7z.StreamsInfo.numCoders]
jb .coders_loop
mov [ebp+_7z.StreamsInfo.numUnPackStreams], 1
mov eax, [esp+4]
dec eax
js return.err
mov [ebp+_7z.StreamsInfo.numBindPairs], eax
push eax
mov ecx, eax
shl ecx, 3
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
mov [ebp+_7z.StreamsInfo.bindPairs], eax
pop ecx
jecxz .noloop3
mov esi, eax
add esi, [_7z.StreamsInfo.folders]
@@:
call _7z.ReadNum
mov [esi], eax
cmp eax, [esp]
jae return.err
call _7z.ReadNum
mov [esi+4], eax
cmp eax, [esp+4]
jae return.err
add esi, 8
loop @b
.noloop3:
pop eax ; numInStreams
pop edx ; numOutStreams
mov [ebp+_7z.StreamsInfo.numOutStreams], edx
sub eax, edx
js return.err
inc eax
mov [ebp+_7z.StreamsInfo.numPackedStreams], eax
mov ecx, eax
push eax
shl ecx, 2
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
mov [ebp+_7z.StreamsInfo.packedStreams], eax
pop ecx
mov esi, eax
add esi, [_7z.StreamsInfo.folders]
cmp ecx, 1
jnz .multiplePackedStreams
mov ebx, [ebp+_7z.StreamsInfo.bindPairs]
add ebx, [_7z.StreamsInfo.folders]
push edx
xor ecx, ecx
.3:
push ebx
mov edx, [ebp+_7z.StreamsInfo.numBindPairs]
@@:
dec edx
js .5
cmp dword [ebx], ecx
jz .4
add ebx, 8
jmp @b
.4:
pop ebx
inc ecx
jmp .3
.5:
pop ebx
pop edx
mov [esi], ecx
jmp .commonPackedStreams
.multiplePackedStreams:
call _7z.ReadNum
mov [esi], eax
add esi, 4
loop .multiplePackedStreams
.commonPackedStreams:
mov ecx, edx
shl ecx, 3
sub ebp, [_7z.StreamsInfo.folders]
call .folders_alloc
add ebp, [_7z.StreamsInfo.folders]
mov [ebp+_7z.StreamsInfo.unpackSizes], eax
pop ecx
xor edx, edx
jecxz @f
mov eax, [_7z.StreamsInfo.folders]
mov eax, [eax+(ecx-1)*4]
add eax, [_7z.StreamsInfo.folders]
mov edx, [eax+_7z.StreamsInfo.numPackedStreams]
add edx, [eax+_7z.StreamsInfo.startPackedStream]
@@:
mov [ebp+_7z.StreamsInfo.startPackedStream], edx
pop ebp
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .folderloop
.nofolders:
call _7z.UnswitchStream
mov ecx, kCodersUnPackSize
call _7z.WaitAttribute
xor ecx, ecx
.6:
cmp ecx, [_7z.StreamsInfo.numFolders]
jae .7
mov eax, [_7z.StreamsInfo.folders]
push ebp
mov ebp, [eax+ecx*4]
add ebp, eax
mov esi, [ebp+_7z.StreamsInfo.numOutStreams]
mov ebp, [ebp+_7z.StreamsInfo.unpackSizes]
add ebp, [_7z.StreamsInfo.folders]
@@:
call _7z.ReadNumber
mov dword [ebp], eax
mov dword [ebp+4], edx
add ebp, 8
dec esi
jnz @b
pop ebp
inc ecx
jmp .6
.7:
; convert all relative addresses to pointers
xor ecx, ecx
mov edx, [_7z.StreamsInfo.folders]
.8:
cmp ecx, [_7z.StreamsInfo.numFolders]
jae .9
lea eax, [edx+ecx*4]
add [eax], edx
mov eax, [eax]
add [eax+_7z.StreamsInfo.bindPairs], edx
add [eax+_7z.StreamsInfo.packedStreams], edx
add [eax+_7z.StreamsInfo.unpackSizes], edx
mov ebx, [eax+_7z.StreamsInfo.numCoders]
add eax, _7z.StreamsInfo.fsz
inc ecx
.11:
dec ebx
js .8
push eax
@@:
cmp dword [eax], 0
jz @f
add [eax], edx
mov eax, [eax]
jmp @b
@@:
pop eax
add eax, 4
jmp .11
.9:
; done
mov eax, [_7z.StreamsInfo.numFolders]
lea edx, [edx+eax*4]
mov [_7z.StreamsInfo.unpackCRCsDefined], edx
add edx, eax
mov [_7z.StreamsInfo.unpackCRCs], edx
@@:
call _7z.ReadNum
test eax, eax
jz .mainloop
cmp eax, kCRC
jz .unpackInfo.crc
call _7z.SkipData
jmp @b
.unpackInfo.crc:
mov esi, [_7z.StreamsInfo.unpackCRCs]
mov ebx, [_7z.StreamsInfo.unpackCRCsDefined]
mov ecx, [_7z.StreamsInfo.numFolders]
call _7z.ReadHashDigests
jmp @b
 
.SubStreamsInfo:
cmp [_7z.StreamsInfo.numFolders], 0
jz return.err
cmp [_7z.StreamsInfo.numSubStreams], 0
jnz return.err
mov ebx, [_7z.StreamsInfo.folders]
.ssloop1:
call _7z.ReadNum
cmp eax, kNumUnPackStream
jz .NumUnPackStream
cmp eax, kCRC
jz .break1
cmp eax, kSize
jz .break1
test eax, eax
jz .break1
call _7z.SkipData
jmp .ssloop1
.NumUnPackStream:
xor ecx, ecx
@@:
call _7z.ReadNum
mov edx, [ebx+ecx*4]
mov [edx+_7z.StreamsInfo.numUnPackStreams], eax
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb @b
jmp .ssloop1
.break1:
; calculate number of substreams and number of defined digests
xor ecx, ecx
xor ebp, ebp
push 0
push eax
xor eax, eax
.ssloop2:
mov edx, [ebx+ecx*4]
mov edx, [edx+_7z.StreamsInfo.numUnPackStreams]
cmp edx, 1
jz @f
inc ebp
@@:
add eax, edx
jc return.err
cmp edx, 1
jnz @f
push eax
mov eax, [_7z.StreamsInfo.unpackCRCsDefined]
cmp byte [eax+ecx], 0
pop eax
jz @f
xor edx, edx
@@:
add [esp+4], edx
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .ssloop2
mov [_7z.StreamsInfo.numSubStreams], eax
imul ecx, eax, 4+8+1
jecxz .noss1
push eax
call [pgalloc]
pop ecx
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.SubStreamsSizes], eax
lea eax, [eax+ecx*8]
mov [_7z.StreamsInfo.SubStreamsCRCsDefined], eax
add eax, ecx
mov [_7z.StreamsInfo.SubStreamsCRCs], eax
@@:
dec eax
mov byte [eax], 0
loop @b
.noss1:
mov ecx, [esp+4]
jecxz @f
imul ecx, 4+1
call [pgalloc]
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], eax
add eax, [esp+4]
mov [_7z.StreamsInfo.tmpSubStreamsCRCs], eax
@@:
test ebp, ebp
jz @f
cmp dword [esp], kSize
jnz return.err
@@:
xor ecx, ecx
mov ebp, [_7z.StreamsInfo.SubStreamsSizes]
.ssloop3:
mov ebx, [_7z.StreamsInfo.folders]
mov ebx, [ebx+ecx*4]
mov eax, [ebx+_7z.StreamsInfo.numUnPackStreams]
dec eax
js .sscont3
push 0
push 0
@@:
dec eax
js @f
push eax
call _7z.ReadNumber
mov [ebp], eax
mov [ebp+4], edx
add ebp, 8
add [esp+4], eax
adc [esp+8], edx
jc return.err
pop eax
jmp @b
@@:
call _7z.GetUnPackSize
sub eax, [esp]
sbb edx, [esp+4]
jc return.err
mov [ebp], eax
mov [ebp+4], edx
add ebp, 8
add esp, 8
.sscont3:
inc ecx
cmp ecx, [_7z.StreamsInfo.numFolders]
jb .ssloop3
pop eax
cmp eax, kSize
jnz @f
call _7z.ReadNum
@@:
cmp eax, kCRC
jz .sscrc
test eax, eax
jz .ssend
call _7z.SkipData
.ssloop4:
call _7z.ReadNum
jmp @b
.sscrc:
pop ecx
push ecx
mov ebx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCs]
call _7z.ReadHashDigests
xor ecx, ecx ; index in out
xor edx, edx ; index in tmp
push -1
pop ebx ; index in folders
.ssloop5:
inc ebx
cmp ebx, [_7z.StreamsInfo.numFolders]
jae .ssloop4
mov eax, [_7z.StreamsInfo.folders]
mov ebp, [eax+ebx*4]
mov ebp, [ebp+_7z.StreamsInfo.numUnPackStreams]
cmp ebp, 1
jnz @f
mov eax, [_7z.StreamsInfo.unpackCRCsDefined]
cmp byte [eax+ebx], 0
jz @f
mov esi, [_7z.StreamsInfo.SubStreamsCRCsDefined]
mov byte [esi+ecx], 1
mov esi, [_7z.StreamsInfo.unpackCRCs]
mov eax, [esi+ebx*4]
mov esi, [_7z.StreamsInfo.SubStreamsCRCs]
mov [esi+ecx*4], eax
inc ecx
jmp .ssloop5
@@:
dec ebp
js .ssloop5
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
mov al, [esi+edx]
mov esi, [_7z.StreamsInfo.SubStreamsCRCsDefined]
mov [esi+ecx], al
mov esi, [_7z.StreamsInfo.tmpSubStreamsCRCs]
mov eax, [esi+edx*4]
mov esi, [_7z.StreamsInfo.SubStreamsCRCs]
mov [esi+ecx*4], eax
inc edx
inc ecx
jmp @b
.ssend:
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
call [pgfree]
and [_7z.StreamsInfo.tmpSubStreamsCRCsDefined], 0
pop ecx
jmp .mainloop
 
.folders_alloc:
push ecx
add ecx, [_7z.StreamsInfo.folders.size]
sub ecx, [_7z.StreamsInfo.folders.alloc]
jbe @f
push edx
or ecx, 0xFFF
inc ecx
add ecx, [_7z.StreamsInfo.folders.alloc]
mov [_7z.StreamsInfo.folders.alloc], ecx
mov edx, [_7z.StreamsInfo.folders]
call [pgrealloc]
pop edx
test eax, eax
jz return.clear
mov [_7z.StreamsInfo.folders], eax
@@:
pop ecx
mov eax, [_7z.StreamsInfo.folders.size]
add [_7z.StreamsInfo.folders.size], ecx
ret
 
.error:
mov ecx, [_7z.StreamsInfo.packSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.folders]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.SubStreamsSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
jecxz @f
call [pgfree]
@@:
jmp open_7z.header_error
.clear:
mov ecx, [_7z.StreamsInfo.packSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.folders]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.SubStreamsSizes]
jecxz @f
call [pgfree]
@@:
mov ecx, [_7z.StreamsInfo.tmpSubStreamsCRCsDefined]
jecxz @f
call [pgfree]
@@:
jmp open_7z.clear
 
uglobal
align 4
_7z.decode.mainbuf dd ?
_7z.decode.pStreams dd ?
_7z.decode.pStreams_def rd 8
_7z.decode.outBufferSize dd ?
_7z.decode.outBufferPtr dd ?
_7z.decode.outBufferRead dd ?
endg
 
virtual at 0
streamInfo:
.fullSize dq ?
.fillBuf dd ? ; procedure which fills the buffer
.bufSize dd ?
.bufDataLen dd ?
.bufPtr dd ?
.size = $
end virtual
 
_7z.decode:
; in: ebx->folder, outBufferSize, outBufferPtr
; N.B. We assume that every coder has 1 output (unpacked) stream.
and [.mainbuf], 0
mov [.pStreams], .pStreams_def
mov [error_proc], .error
mov [clear_proc], .clear
call .init
and [.outBufferRead], 0
@@:
push edi
mov eax, [ebx+_7z.StreamsInfo.mainOutStream]
mov esi, [.pStreams]
mov eax, [esi+eax*4]
call fillBuf
mov ecx, [eax+streamInfo.bufSize]
mov esi, [eax+streamInfo.bufPtr]
mov edi, [.outBufferPtr]
add edi, [.outBufferRead]
add [.outBufferRead], ecx
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
pop edi
mov eax, [.outBufferRead]
cmp eax, [.outBufferSize]
jb @b
mov ecx, [.pStreams]
cmp ecx, .pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [.mainbuf]
jecxz @f
call [pgfree]
@@:
mov [error_proc], _7z.ReadAndDecodePackedStreams.error
mov [clear_proc], _7z.ReadAndDecodePackedStreams.clear
ret
 
.error:
mov ecx, [.pStreams]
cmp ecx, .pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [.mainbuf]
jecxz @f
call [pgfree]
@@:
jmp _7z.ReadAndDecodePackedStreams.error
.clear:
mov ecx, [.pStreams]
cmp ecx, .pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [.mainbuf]
jecxz @f
call [pgfree]
@@:
jmp _7z.ReadAndDecodePackedStreams.clear
 
.init:
; We use stack to keep some information on streams,
; to avoid stack overflow we limit possible number of coders.
; Anyway, in real life maximum number of coders is 5
; (password protection filter + BCJ2 filter + 3 LZMA coders),
; from command line user can define more coders, but
; archive with, say, 32 coders is most likely bogus.
cmp [ebx+_7z.StreamsInfo.numCoders], 128
ja return.err
; allocate space for streams info array
mov eax, .pStreams_def
mov ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
add ecx, [ebx+_7z.StreamsInfo.numCoders]
cmp ecx, 8
jbe @f
shl ecx, 2
call [pgalloc]
test eax, eax
jz return.clear
@@:
mov [.pStreams], eax
; calculate size of buffers required for decoders
xor ecx, ecx
push ecx
mov ebp, [ebx+_7z.StreamsInfo.unpackSizes]
.calcbufsz:
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
jnc .known_id
.unknown_method_id:
movzx esi, byte [eax+4]
lea ecx, [eax+5]
mov ebx, aUnknownMethod.z
@@:
dec esi
js @f
mov byte [ebx], ' '
inc ebx
mov al, [ecx]
push eax
shr al, 4
cmp al, 10
sbb al, 69h
das
mov [ebx], al
inc ebx
pop eax
and al, 0xF
cmp al, 10
sbb al, 69h
das
mov [ebx], al
inc ebx
inc ecx
jmp @b
@@:
mov byte [ebx], 0
push ContinueBtn
push 1
push aUnknownMethod_ptr
push 1
call [SayErr]
jmp return.clear
iglobal
if lang eq ru
aUnknownMethod db '¥¨§¢¥áâ­ë© ¬¥â®¤:'
else
aUnknownMethod db 'Unknown method:'
end if
.z:
times 16*3+1 db 0
aUnknownMethod_ptr dd aUnknownMethod
endg
.known_id:
movzx esi, byte [eax+4]
lea esi, [esi+eax+17]
call [_7z.GetBufSizeTable+edx*4]
add eax, 3
and al, not 3
add [esp], eax
jc .nomem
cmp dword [ebp+4], 0
jnz @f
cmp dword [ebp], edx
jae @f
mov edx, [ebp]
@@:
add edx, 0xF
and edx, not 0xF
add [esp], edx
jc .nomem
add ebp, 8
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb .calcbufsz
; add 4 pages for each of not binded input streams
mov ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
shl ecx, 14
add [esp], ecx
;; calculate free RAM
; call [getfreemem]
; sub eax, 64 ; keep at least 64 Kb of free RAM
; jbe .nomem
; pop ecx
; push ecx
; add ecx, 0x3FF
; shr ecx, 10
; cmp eax, ecx
; jae .memok
jmp .memok
.nomem:
push ContinueBtn
push 1
push aNoFreeRam_ptr
push 1
call [SayErr]
jmp return.clear
.memok:
; allocate streamInfos
pop ecx
call [pgalloc]
test eax, eax
jz return.clear
mov [.mainbuf], eax
; initialize streamInfos for decoders
xor ecx, ecx
mov ebp, [ebx+_7z.StreamsInfo.unpackSizes]
mov edx, [.pStreams]
.init1:
mov [edx], eax
add edx, 4
push edx
push dword [ebp]
pop dword [eax]
push dword [ebp+4]
pop dword [eax+4]
and dword [eax+streamInfo.size], 0
push eax
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
movzx esi, byte [eax+4]
lea esi, [esi+eax+17]
call [_7z.GetBufSizeTable+edx*4]
pop esi
push esi
add eax, 3
and al, not 3
add [esp], eax
pop [esi+streamInfo.bufPtr]
push [esi+streamInfo.bufPtr]
cmp dword [ebp+4], 0
jnz @f
cmp dword [ebp], edx
jae @f
mov edx, [ebp]
@@:
add edx, 0xF
and edx, not 0xF
mov [esi+streamInfo.bufSize], edx
and [esi+streamInfo.bufDataLen], 0
pop eax
add eax, edx
pop edx
add ebp, 8
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb .init1
; initialize streamInfos for input streams
xor ecx, ecx
@@:
mov [edx], eax
add edx, 4
mov esi, [_7z.CurInStream]
inc [_7z.CurInStream]
shl esi, 3
add esi, [_7z.StreamsInfo.packSizes]
push dword [esi]
pop dword [eax]
push dword [esi+4]
pop dword [eax+4]
mov [eax+streamInfo.fillBuf], fillBufFromInStream
lea esi, [eax+streamInfo.size+8]
mov [eax+streamInfo.bufPtr], esi
mov [eax+streamInfo.bufSize], 0x4000 - streamInfo.size - 8
and [eax+streamInfo.bufDataLen], 0
mov esi, dword [_7z.StreamsInfo.dataOffset]
mov dword [eax+streamInfo.size], esi
mov esi, dword [_7z.StreamsInfo.dataOffset+4]
mov dword [eax+streamInfo.size+4], esi
mov esi, [eax]
add dword [_7z.StreamsInfo.dataOffset], esi
mov esi, [eax+4]
adc dword [_7z.StreamsInfo.dataOffset+4], esi
add eax, 0x4000
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
jb @b
; initialize links between streams
push -1
mov edx, [ebx+_7z.StreamsInfo.mainOutStream]
xor ecx, ecx
.init_links:
mov eax, [ebx+_7z.StreamsInfo.fsz+edx*4]
movzx esi, byte [eax+4]
cmp ecx, [eax+esi+5]
jb @f
pop ecx
cmp ecx, -1
jz .inited_links
pop edx
jmp .init_links
@@:
push edx
push ecx
@@:
dec edx
js @f
mov eax, [ebx+_7z.StreamsInfo.fsz+edx*4]
movzx esi, byte [eax+4]
add ecx, [eax+esi+5]
jmp @b
@@:
mov esi, [ebx+_7z.StreamsInfo.bindPairs]
mov edx, [ebx+_7z.StreamsInfo.numBindPairs]
@@:
add esi, 8
dec edx
js .link_to_in
cmp ecx, [esi-8]
jnz @b
pop ecx
pop edx
mov eax, [.pStreams]
mov eax, [eax+edx*4]
lea eax, [eax+streamInfo.size+ecx*4]
push edx
inc ecx
push ecx
mov edx, [esi-4]
mov ecx, [.pStreams]
mov ecx, [ecx+edx*4]
mov [eax], ecx
cmp dword [ecx+streamInfo.size], 0
jnz return.err
xor ecx, ecx
jmp .init_links
.link_to_in:
mov esi, [ebx+_7z.StreamsInfo.packedStreams]
mov edx, [ebx+_7z.StreamsInfo.numPackedStreams]
@@:
dec edx
js return.err
cmp ecx, [esi+edx*4]
jnz @b
add edx, [ebx+_7z.StreamsInfo.numCoders]
mov esi, [.pStreams]
mov eax, [esi+edx*4]
pop ecx
pop edx
mov esi, [esi+edx*4]
mov [esi+streamInfo.size+ecx*4], eax
inc ecx
jmp .init_links
.inited_links:
; initialize all decoders
; bool zzz_init_decoder(stream_info* ebp, esi->params, [esi-4]=params_size);
xor ecx, ecx
.init_decoders:
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
movzx esi, byte [eax+4]
mov ebp, [.pStreams]
mov ebp, [ebp+ecx*4]
cmp dword [esi+eax], 0
jz @f
cmp dword [ebp+streamInfo.size], 0
jz return.err
@@:
lea esi, [esi+eax+17]
push ebx ecx edi
xor ebx, ebx
call [_7z.InitTable+edx*4]
pop edi ecx ebx
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb .init_decoders
ret
 
fillBuf:
and [eax+streamInfo.bufDataLen], 0
fillBufNozero:
pushad
mov edx, [eax+streamInfo.bufSize]
sub edx, [eax+streamInfo.bufDataLen]
cmp dword [eax+streamInfo.fullSize+4], 0
jnz .full
mov ecx, dword [eax+streamInfo.fullSize]
cmp ecx, edx
jbe @f
.full:
mov ecx, edx
@@:
sub dword [eax+streamInfo.fullSize], ecx
sbb dword [eax+streamInfo.fullSize+4], 0
mov edi, [eax+streamInfo.bufPtr]
add edi, [eax+streamInfo.bufDataLen]
add [eax+streamInfo.bufDataLen], ecx
jmp [eax+streamInfo.fillBuf]
 
fillBufFromInStream:
push eax
push dword [eax+streamInfo.size+4]
push dword [eax+streamInfo.size]
push 0
push [inStream]
call [seek]
pop eax
push eax
push ecx
push edi
push [inStream]
call [read]
cmp eax, ecx
pop eax
jnz .error
add dword [eax+streamInfo.size], ecx
adc dword [eax+streamInfo.size+4], 0
popad
ret
.error:
push ContinueBtn
push 1
push aReadError_ptr
push 1
call [SayErr]
jmp return.clear
 
_7z.GetCoder:
; in: eax->coder
; out: edx = coder type
xor edx, edx
; Copy decoder: method ID = [size=01] 00, NumInStreams = NumOutStreams = 1
cmp word [eax+4], 0x0001
jnz @f
cmp dword [eax+6], 1
jz .ret
@@:
inc edx
; LZMA decoder: method ID = [size=03] 03 01 01, NumInStreams = NumOutStreams = 1
cmp dword [eax+4], 0x01010303
jnz @f
cmp dword [eax+8], 1
jz .ret
@@:
inc edx
; PPMD decoder: method ID = [size=03] 03 04 01, NumInStreams = NumOutStreams = 1
cmp dword [eax+4], 0x01040303
jnz @f
cmp dword [eax+8], 1
jz .ret
@@:
inc edx
; BCJ filter: method ID = [size=04] 03 03 01 03, NumInStreams = NumOutStreams = 1
cmp byte [eax+4], 4
jnz @f
cmp dword [eax+5], 0x03010303
jnz @f
cmp dword [eax+9], 1
jz .ret
@@:
inc edx
; BCJ2 filter: method ID = [size=04] 03 03 01 1B, NumInStreams = 4, NumOutStreams = 1
cmp byte [eax+4], 4
jnz @f
cmp dword [eax+5], 0x1B010303
jnz @f
cmp dword [eax+9], 4
jz .ret
@@:
inc edx
; 7z-AES cryptor: method ID = [size=04] 06 F1 07 01, NumInStreams = NumOutStreams = 1
cmp byte [eax+4], 4
jnz @f
cmp dword [eax+5], 0x0107F106
jnz @f
cmp dword [eax+9], 1
jz .ret
@@:
stc
.ret:
ret
 
iglobal
align 4
label _7z.GetBufSizeTable dword
dd copy_get_buf_size
dd lzma_get_buf_size
dd ppmd_get_buf_size
dd bcj_get_buf_size
dd bcj2_get_buf_size
dd aes7z_get_buf_size
label _7z.InitTable dword
dd copy_init_decoder
dd lzma_init_decoder
dd ppmd_init_decoder
dd bcj_init_decoder
dd bcj2_init_decoder
dd aes7z_init_decoder
endg
 
copy_get_buf_size:
mov eax, streamInfo.size+8
mov edx, 0x10000
ret
 
copy_init_decoder:
mov [ebp+streamInfo.fillBuf], copy_fillBuf
and dword [ebp+streamInfo.size+4], 0
ret
 
copy_fillBuf:
push eax
mov esi, [eax+streamInfo.size+4]
mov eax, [eax+streamInfo.size]
.redo:
push ecx
mov edx, [eax+streamInfo.bufDataLen]
sub edx, esi
cmp ecx, edx
jb @f
mov ecx, edx
@@:
sub [esp], ecx
add esi, [eax+streamInfo.bufPtr]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
pop ecx
jecxz .done
cmp dword [eax+streamInfo.fullSize+4], 0
jnz @f
cmp dword [eax+streamInfo.fullSize], ecx
jb return.err
@@:
call fillBuf
xor esi, esi
jmp .redo
.done:
sub esi, [eax+streamInfo.bufPtr]
pop eax
mov [eax+streamInfo.size+4], esi
popad
ret
 
; int __stdcall ReadFolder([esp+4] = HANDLE hPlugin,
; [esp+8] = unsigned dirinfo_start, [esp+12] = unsigned dirinfo_size,
; [esp+16] = void* dirdata);
ReadFolder_7z:
; init header
mov edi, [esp+16]
mov ecx, 32/4
xor eax, eax
rep stosd
mov byte [edi-32], 1 ; version
mov ebp, [esp+4]
; get current directory
lea ebx, [ebp+handle_7z.root.subfolders]
cmp [ebp+handle_7z.curdir], 0
jz @f
mov ebx, [ebp+handle_7z.curdir]
add ebx, file_in_7z.subfolders
@@:
mov ecx, [ebx+16]
mov [edi-24], ecx ; number of files
; edi points to BDFE
push 6 ; assume EOF
pop eax
sub ecx, [esp+8]
ja @f
and dword [edi-28], 0 ; number of files read
ret 10h
@@:
cmp ecx, [esp+12]
jb @f
mov ecx, [esp+12]
xor eax, eax ; OK
@@:
mov [edi-28], ecx
push eax
; copy files data
test ecx, ecx
jz .done
; seek to required item
mov eax, [esp+8+4]
mov esi, [ebx]
.0:
test esi, esi
jnz .1
mov esi, [ebx+8]
.1:
add esi, ebp
dec eax
js .2
mov esi, [esi+file_in_7z.next]
jmp .0
.2:
.copy:
cmp [esi+file_in_7z.bPseudoFolder], 0
jnz .pseudo
xor eax, eax
cmp [esi+file_in_7z.bAttrDefined], 0
jz @f
mov eax, [esi+file_in_7z.attr]
@@:
stosd
xor eax, eax
stosd
push esi ecx
add esi, file_in_7z.CreationTime
mov ecx, 8
rep movsd
pop ecx esi
mov edx, [esi+file_in_7z.name]
push edi
@@:
mov al, [edx]
inc edx
stosb
test al, al
jnz @b
pop edi
.cont:
add edi, 264
mov esi, [esi+file_in_7z.next]
test esi, esi
jnz @f
mov esi, [ebx+8]
@@:
add esi, ebp
loop .copy
jmp .done
.pseudo:
push 0x10 ; attributes: folder
pop eax
stosd
xor eax, eax
stosd
push ecx esi
lea esi, [ebp+handle_7z.host_datetime]
mov ecx, 6
rep movsd
pop esi
stosd
stosd
push edi esi
mov ecx, [esi+file_in_7z.namelen]
mov esi, [esi+file_in_7z.name]
rep movsb
mov byte [edi], 0
pop esi edi ecx
jmp .cont
.done:
pop eax
ret 10h
 
; bool __stdcall SetFolder([esp+4] = HANDLE hPlugin,
; [esp+8] = const char* relative_path, [esp+12] = const char* absolute_path);
SetFolder_7z:
mov ebp, [esp+4]
mov edx, [ebp+handle_7z.curdir]
mov esi, [esp+8]
cmp dword [esi], '..'
jz .toparent
xor ecx, ecx
@@:
inc ecx
cmp byte [esi+ecx], 0
jnz @b
mov ebx, [ebp+handle_7z.root.subfolders]
test edx, edx
jz .scan
mov ebx, [edx+file_in_7z.subfolders]
.scan:
test ebx, ebx
jz .err
add ebx, ebp
cmp [ebx+file_in_7z.namelen], ecx
jnz .cont
push ecx esi
mov edi, [ebx+file_in_7z.name]
repz cmpsb
pop esi ecx
jz .set
.cont:
mov ebx, [ebx+file_in_7z.next]
jmp .scan
.toparent:
test edx, edx
jz .err
mov ebx, [edx+file_in_7z.parent]
test ebx, ebx
jz @f
add ebx, ebp
@@:
.set:
mov [ebp+handle_7z.curdir], ebx
mov al, 1
ret 12
.err:
xor eax, eax
ret 12
 
; ebp=hPlugin, eax->item, edi->info
getattr_7z:
cmp [eax+file_in_7z.bPseudoFolder], 0
jnz .pseudo
lea esi, [eax+file_in_7z.attr]
movsd
xor eax, eax
stosd
add esi, -(file_in_7z.attr+4) + file_in_7z.CreationTime
mov ecx, 8
rep movsd
ret
.pseudo:
mov esi, [eax+file_in_7z.name]
mov ecx, [eax+file_in_7z.namelen]
push 0x10 ; attributes: folder
pop eax
stosd
xor eax, eax
stosd
push ecx esi
lea esi, [ebp+handle_7z.host_datetime]
push 6
pop ecx
rep movsd
pop esi ecx
stosd
stosd
rep movsb
mov byte [edi], 0
ret
 
virtual at 0
file_handle_7z:
.type dd ?
.context dd ?
.pos dq ?
.base dd ? ; handle of archive
.item dd ? ; pointer to file_in_7z
.mainStream dd ? ; (pointer in context)
.bError db ?
rb 3
.size = $
end virtual
 
iglobal
align 4
handle_table_7z dd handle_table_7z,handle_table_7z
endg
 
; ebp=hPlugin, eax->item, edi=mode
open_file_7z:
cmp [eax+file_in_7z.bHasStream], 0
jnz @f
mov eax, empty_7z_handle
ret
@@:
mov ecx, [ebp+handle_7z.password_len]
inc ecx
setnz [bPasswordDefined]
jz @f
dec ecx
lea esi, [ebp+handle_7z.password]
push edi
mov edi, password_unicode
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
pop edi
@@:
mov [hOut], ecx
mov [_7z.decode.mainbuf], ecx
mov ecx, [ebp+handle_7z.host]
mov [inStream], ecx
mov [_7z.decode.pStreams], _7z.decode.pStreams_def
push eax
mov [_esp], esp
mov [_ebp], ebp
mov [error_proc], .error
mov [clear_proc], .clear
mov ebx, [ebp+handle_7z.folders]
mov ecx, [eax+file_in_7z.folder]
cmp [ebp+handle_7z.last_folder], ecx
jnz .nolast
mov edx, dword [eax+file_in_7z.folderStart]
sub edx, dword [ebp+handle_7z.last_pos]
mov esi, dword [eax+file_in_7z.folderStart+4]
sbb esi, dword [ebp+handle_7z.last_pos+4]
jb .nolast
xor ecx, ecx
xchg ecx, [ebp+handle_7z.last_context]
mov [_7z.decode.mainbuf], ecx
mov eax, [ebp+handle_7z.last_main_stream]
mov dword [eax+streamInfo.fullSize], edx
mov dword [eax+streamInfo.fullSize+4], esi
or [ebp+handle_7z.last_folder], -1
pop esi
push esi
jmp .commonl
.nolast:
mov ebx, [ebx+ecx*4]
mov eax, [ebx+_7z.StreamsInfo.startPackedStream]
mov [_7z.CurInStream], eax
mov eax, dword [ebx+_7z.StreamsInfo.packOffset]
mov dword [_7z.StreamsInfo.dataOffset], eax
mov eax, dword [ebx+_7z.StreamsInfo.packOffset+4]
mov dword [_7z.StreamsInfo.dataOffset+4], eax
mov eax, [ebp+handle_7z.packSizes]
mov [_7z.StreamsInfo.packSizes], eax
push ebp
call _7z.decode.init
pop ebp
mov eax, [ebx+_7z.StreamsInfo.mainOutStream]
mov esi, [_7z.decode.pStreams]
mov eax, [esi+eax*4]
pop esi
push esi
mov ecx, dword [esi+file_in_7z.folderStart]
mov dword [eax+streamInfo.fullSize], ecx
mov ecx, dword [esi+file_in_7z.folderStart+4]
mov dword [eax+streamInfo.fullSize+4], ecx
.commonl:
call skip_7z
mov ecx, dword [esi+file_in_7z.UnPackSize]
mov dword [eax+streamInfo.fullSize], ecx
mov edx, dword [esi+file_in_7z.UnPackSize+4]
mov dword [eax+streamInfo.fullSize+4], edx
test edx, edx
jnz .nomemstream
if defined LIMIT_FOR_MEM_STREAM
cmp ecx, LIMIT_FOR_MEM_STREAM
ja .nomemstream
end if
push eax ecx
add ecx, 0x3FF
shr ecx, 10 ; get size in Kb
call [getfreemem]
shr eax, 2
cmp ecx, eax
pop ecx eax
ja .nomemstream
; create memory stream and unpack to memory
push eax ecx
add ecx, mem_stream.buf
call [pgalloc]
test eax, eax
jz return.clear
mov edi, eax
pop ecx
push edi
mov [hOut], eax
xor eax, eax ; type_mem_stream
stosd ; mem_stream.type
mov eax, ecx
stosd ; mem_stream.size
xor eax, eax
stosd ; mem_stream.pos
mov eax, [esp+4]
push esi
push ecx edi
call read_7z_to_buf
pop esi ecx
mov ebx, [esp+12]
cmp [ebx+file_in_7z.bCRCDefined], 0
jz @f
call crc
cmp eax, [ebx+file_in_7z.FileCRC]
jnz return.err
@@:
pop esi
xor ecx, ecx
xchg ecx, [_7z.decode.mainbuf]
xchg ecx, [ebp+handle_7z.last_context]
jecxz @f
call [pgfree]
@@:
and [hOut], 0
mov eax, [esi+file_in_7z.folder]
mov [ebp+handle_7z.last_folder], eax
mov eax, [esp+4]
mov [ebp+handle_7z.last_main_stream], eax
mov ecx, dword [esi+file_in_7z.UnPackSize]
add ecx, dword [esi+file_in_7z.folderStart]
mov dword [ebp+handle_7z.last_pos], ecx
mov ecx, dword [esi+file_in_7z.UnPackSize+4]
adc ecx, dword [esi+file_in_7z.folderStart+4]
mov dword [ebp+handle_7z.last_pos+4], ecx
call .done
pop eax edi ecx
ret
.nomemstream:
mov edi, eax
push esi
mov esi, handle_table_7z
push file_handle_7z.size
pop ecx
call alloc_handle
pop esi
test eax, eax
jz .clear
mov [eax+file_handle_7z.type], type_7z
xor edx, edx
mov dword [eax+file_handle_7z.pos], edx
mov dword [eax+file_handle_7z.pos+4], edx
mov [eax+file_handle_7z.bError], dl
xchg edx, [_7z.decode.mainbuf]
mov [eax+file_handle_7z.context], edx
mov [eax+file_handle_7z.mainStream], edi
mov [eax+file_handle_7z.base], ebp
mov [eax+file_handle_7z.item], esi
push eax
call .done
pop eax ecx
ret
 
.done:
cmp [bPasswordDefined], 0
jz @f
mov ecx, [password_size]
mov [ebp+handle_7z.password_len], ecx
mov esi, password_unicode
lea edi, [ebp+handle_7z.password]
shr ecx, 1
rep movsd
adc ecx, ecx
rep movsw
@@:
jmp .clear
 
.error:
cmp [bPasswordDefined], 0
jz .realerror
push CancelPassBtn
push 2
push aArchiveDataErrorPass_ptr
push 1
call [SayErr]
cmp al, 1
jnz .clear
; user wants to re-enter password
call .clear
pop eax
jmp open_file_7z
.realerror:
push ContinueBtn
push 1
push aArchiveDataError_ptr
push 1
call [SayErr]
.clear:
mov ecx, [_7z.decode.pStreams]
cmp ecx, _7z.decode.pStreams_def
jz @f
call [pgfree]
@@:
mov ecx, [_7z.decode.mainbuf]
jecxz @f
call [pgfree]
@@:
mov ecx, [hOut]
jecxz @f
call [pgfree]
@@:
cmp esp, [_esp]
jnz @f
pop eax
@@:
xor eax, eax
ret
 
read_7z_to_buf:
mov esi, [eax+streamInfo.bufDataLen]
cmp esi, [eax+streamInfo.bufSize]
jnz @f
xor esi, esi
mov [eax+streamInfo.bufDataLen], esi
@@:
call fillBufNozero
mov ecx, [eax+streamInfo.bufDataLen]
sub ecx, esi
add esi, [eax+streamInfo.bufPtr]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
cmp dword [eax+streamInfo.fullSize], 0
jnz read_7z_to_buf
ret
 
skip_7z:
push edx
mov edx, [eax+streamInfo.bufDataLen]
cmp edx, [eax+streamInfo.bufSize]
jnz @f
and [eax+streamInfo.bufDataLen], 0
@@:
pop edx
call fillBufNozero
cmp dword [eax+streamInfo.fullSize], 0
jnz skip_7z
cmp dword [eax+streamInfo.fullSize+4], 0
jnz skip_7z
ret
 
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
read_7z:
mov eax, [ebx+file_handle_7z.mainStream]
test eax, eax
jz .ret ; empty stream - return 0 bytes read
cmp [ebx+file_handle_7z.bError], 0
jnz .reterr
mov ecx, [ebx+file_handle_7z.base]
mov ecx, [ecx+handle_7z.host]
mov [inStream], ecx
mov edi, [esp+8]
mov ecx, [esp+12]
mov dword [eax+streamInfo.fullSize], ecx
and dword [eax+streamInfo.fullSize+4], 0
jecxz .nodata
mov [_esp], esp
mov [_ebp], ebp
mov [error_proc], .error
mov [clear_proc], .clear ; should not be called
mov esi, [ebx+file_handle_7z.item]
mov edx, dword [esi+file_in_7z.UnPackSize]
mov esi, dword [esi+file_in_7z.UnPackSize+4]
sub edx, dword [ebx+file_handle_7z.pos]
sbb esi, dword [ebx+file_handle_7z.pos+4]
jnz .do
cmp edx, ecx
jae .do
mov dword [eax+streamInfo.fullSize], edx
.do:
call read_7z_to_buf
.nodata:
sub edi, [esp+8]
mov eax, edi
add dword [ebx+file_handle_7z.pos], eax
adc dword [ebx+file_handle_7z.pos+4], 0
.ret:
ret 12
 
.error:
.clear:
mov ebx, [esp+4]
mov [ebx+file_handle_7z.bError], 1
push ContinueBtn
push 1
push aArchiveDataError_ptr
push 1
call [SayErr]
.reterr:
or eax, -1
ret 12
 
; void __stdcall setpos(HANDLE hFile, __int64 pos);
setpos_7z:
cmp [ebx+file_handle_7z.context], 0
jz .ret
mov edi, [ebx+file_handle_7z.base]
mov ecx, [edi+handle_7z.host]
mov [inStream], ecx
mov [_esp], esp
mov [_ebp], ebp
mov [error_proc], read_7z.error
mov [clear_proc], read_7z.clear ; should not be called
cmp [ebx+file_handle_7z.bError], 0
jnz .backward ; if was error, force reinitialization
mov ecx, [esp+8]
mov edx, [esp+12]
sub ecx, dword [ebx+file_handle_7z.pos]
sbb edx, dword [ebx+file_handle_7z.pos+4]
jb .backward
; move forward - skip some data
mov eax, [ebx+file_handle_7z.mainStream]
mov dword [eax+streamInfo.fullSize], ecx
mov dword [eax+streamInfo.fullSize+4], edx
call skip_7z
add dword [ebx+file_handle_7z.pos], ecx
adc dword [ebx+file_handle_7z.pos], edx
.ret:
ret 12
.backward:
; move backward - reinitialize and skip start data
mov [ebx+file_handle_7z.bError], 0
mov ebp, [ebx+file_handle_7z.context]
mov eax, [ebx+file_handle_7z.item]
mov ebx, [edi+handle_7z.folders]
mov eax, [eax+file_in_7z.folder]
mov ebx, [ebx+eax*4]
; initialize streamInfos for decoders
xor ecx, ecx
mov esi, [ebx+_7z.StreamsInfo.unpackSizes]
@@:
lodsd
mov [ebp], eax
lodsd
mov [ebp+4], eax
and [ebp+streamInfo.bufDataLen], 0
push esi
mov eax, [ebx+_7z.StreamsInfo.fsz+ecx*4]
call _7z.GetCoder
movzx esi, byte [eax+4]
lea esi, [esi+eax+17]
push ebx ecx edi
mov bl, 1
call [_7z.InitTable+edx*4]
pop edi ecx ebx esi
mov edx, [ebp+streamInfo.bufSize]
mov ebp, [ebp+streamInfo.bufPtr]
add ebp, edx
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numCoders]
jb @b
; initialize streamInfos for input streams
xor ecx, ecx
mov esi, [ebx+_7z.StreamsInfo.startPackedStream]
shl esi, 3
add esi, [edi+handle_7z.packSizes]
mov edi, dword [ebx+_7z.StreamsInfo.packOffset]
mov edx, dword [ebx+_7z.StreamsInfo.packOffset+4]
@@:
mov dword [ebp+streamInfo.size], edi
mov dword [ebp+streamInfo.size+4], edx
and [ebp+streamInfo.bufDataLen], 0
lodsd
add edi, eax
mov [ebp], eax
lodsd
adc edx, eax
mov [ebp+4], eax
add ebp, 0x4000
inc ecx
cmp ecx, [ebx+_7z.StreamsInfo.numPackedStreams]
jb @b
mov ebx, [esp+4]
mov esi, [ebx+file_handle_7z.item]
mov eax, [ebx+file_handle_7z.mainStream]
mov ecx, dword [esi+file_in_7z.folderStart]
add ecx, [esp+8]
mov dword [eax+streamInfo.fullSize], ecx
mov ecx, dword [esi+file_in_7z.folderStart+4]
adc ecx, [esp+12]
mov dword [eax+streamInfo.fullSize+4], ecx
and dword [ebx+file_handle_7z.pos], 0
and dword [ebx+file_handle_7z.pos+4], 0
and [eax+streamInfo.bufDataLen], 0
call skip_7z
mov eax, [esp+8]
mov dword [ebx+file_handle_7z.pos], eax
mov eax, [esp+12]
mov dword [ebx+file_handle_7z.pos+4], eax
ret 12
 
close_file_7z:
mov ecx, [ebx+file_handle_7z.context]
jecxz .ret
cmp [ebx+file_handle_7z.bError], 0
jnz @f
push ebp
mov ebp, [ebx+file_handle_7z.base]
xchg ecx, [ebp+handle_7z.last_context]
mov eax, [ebx+file_handle_7z.item]
mov edx, [eax+file_in_7z.folder]
mov [ebp+handle_7z.last_folder], edx
mov edx, [ebx+file_handle_7z.mainStream]
mov [ebp+handle_7z.last_main_stream], edx
mov edx, dword [eax+file_in_7z.folderStart+4]
mov eax, dword [eax+file_in_7z.folderStart]
add eax, dword [ebx+file_handle_7z.pos]
adc edx, dword [ebx+file_handle_7z.pos+4]
mov dword [ebp+handle_7z.last_pos], eax
mov dword [ebp+handle_7z.last_pos+4], edx
pop ebp
@@:
jecxz @f
call [pgfree]
@@:
mov esi, ebx
call free_handle
.ret:
ret 4
 
iglobal
cur_stamp dd 0
endg
 
uglobal
tmp_bdfe rb 304
endg
 
GetFiles_7z:
mov ecx, [ebp+handle_7z.NumFiles]
test ecx, ecx
jz .ret
lea ebx, [ebp+handle_7z.basesize]
inc [cur_stamp]
.loop:
push ecx
mov esi, [ebx+file_in_7z.fullname]
mov edx, [ebp+handle_7z.curdir]
test edx, edx
jz .incur
mov eax, [cur_stamp]
mov [edx+file_in_7z.stamp], eax
mov edi, [edx+file_in_7z.fullname]
mov ecx, [edx+file_in_7z.namelen]
add ecx, [edx+file_in_7z.name]
sub ecx, edi
repz cmpsb
jnz .cont
.incur:
cmp byte [esi], '/'
jnz @f
inc esi
@@:
mov ecx, [esp+12] ; NumItems
mov edx, [esp+16] ; items
cmp ecx, -1
jz .ok
.check:
sub ecx, 1
js .cont
push esi
mov edi, [edx]
add edi, 40
@@:
lodsb
scasb
jnz @f
test al, al
jz .ok2
jmp @b
@@:
pop esi
cmp al, '/'
jnz @f
cmp byte [edi-1], 0
jz .ok
@@:
add edx, 4
jmp .check
.ok2:
pop esi
.ok:
; add all parents directories if needed
.parloope:
mov ecx, [ebx+file_in_7z.parent]
jecxz .pardone
add ecx, ebp
mov eax, [cur_stamp]
cmp [ecx+file_in_7z.stamp], eax
jz .pardone
.parloopi:
mov edx, ecx
mov ecx, [ecx+file_in_7z.parent]
jecxz @f
add ecx, ebp
cmp [ecx+file_in_7z.stamp], eax
jnz .parloopi
@@:
mov [edx+file_in_7z.stamp], eax
push esi
mov eax, edx
mov edi, tmp_bdfe
push edi
sub esi, [ebx+file_in_7z.fullname]
add esi, [edx+file_in_7z.fullname]
push esi
call getattr_7z
mov eax, [esp+16+20]
call eax
pop esi
test al, al
jz .forced_exit
jmp .parloope
.pardone:
cmp [ebx+file_in_7z.bIsDirectory], 0
jz .addfile
mov eax, [cur_stamp]
cmp [ebx+file_in_7z.stamp], eax
jz .cont
mov [ebx+file_in_7z.stamp], eax
push esi
mov eax, ebx
mov edi, tmp_bdfe
push edi
push esi
call getattr_7z
mov eax, [esp+16+20]
call eax
pop esi
test al, al
jz .forced_exit
jmp .cont
.addfile:
push ebx esi
push 11h
pop edi
mov eax, ebx
call open_file_7z
pop esi ebx
test eax, eax
jz .cont
push eax
push eax
mov edi, tmp_bdfe
push edi
push esi
mov eax, ebx
call getattr_7z
mov eax, [esp+20+16]
call eax
pop ecx
push eax
push ebx
push ecx
call myclose
pop ebx
pop eax
test al, al
jz .forced_exit
.cont:
add ebx, file_in_7z.size
pop ecx
dec ecx
jnz .loop
.ret:
ret 20
.forced_exit:
pop ecx
jmp .ret
/programs/fs/kfar/trunk/kfar_arc/7zaes.inc
0,0 → 1,216
; Password handling in 7-Zip: "7zAES" filter (SHA256 + AES256).
; Ported from C++ sources of 7-Zip (c) Igor Pavlov.
aes7z_decoder:
virtual at 0
.outStream rb streamInfo.size
.inStream dd ?
.inLen dd ?
.inPtr dd ?
.bufRest dd ?
; key data
.NumCyclesPower dd ?
.SaltSize dd ?
.Salt rb 16
; AES data
.iv rb 16
.Key rb 32
.nr dd ?
.KeyExpanded rb 32*15
.size = $
end virtual
 
.fillBuf:
mov esi, [eax+.inPtr]
mov ebp, eax
add edi, [eax+.bufRest]
sub ecx, [eax+.bufRest]
js .rest1
and [eax+.bufRest], 0
.mainloop:
test ecx, ecx
jz .done
sub [ebp+.inLen], 16
js .refill
.refilled:
push esi edi ecx
mov ebx, edi
lea edi, [ebp+.nr]
call aes_decode
pop ecx edi esi
mov eax, dword [ebp+.iv]
xor [edi], eax
lodsd
mov dword [ebp+.iv], eax
mov eax, dword [ebp+.iv+4]
xor [edi+4], eax
lodsd
mov dword [ebp+.iv+4], eax
mov eax, dword [ebp+.iv+8]
xor [edi+8], eax
lodsd
mov dword [ebp+.iv+8], eax
mov eax, dword [ebp+.iv+12]
xor [edi+12], eax
lodsd
mov dword [ebp+.iv+12], eax
add edi, 16
sub ecx, 16
jns .mainloop
.rest1:
neg ecx
mov [ebp+.bufRest], ecx
.done:
mov [ebp+.inPtr], esi
popad
ret
 
.refill:
mov edx, [ebp+.inLen]
add edx, 16
jnz .rest
js return.err
mov eax, [ebp+.inStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
test edx, edx
jz return.err
mov esi, [eax+streamInfo.bufPtr]
mov [ebp+.inLen], edx
sub [ebp+.inLen], 16
jns .refilled
.rest:
; ASSERT([eax+streamInfo.fullSize] == 0);
sub edx, ecx
jb return.err
add ecx, edx
rep movsb
mov [ebp+.bufRest], edx
jmp .done
 
aes7z_get_buf_size:
mov eax, aes7z_decoder.size
mov edx, 0x4000
ret
 
aes7z_init_decoder:
; zero all
xor eax, eax
mov [ebp+aes7z_decoder.inLen], eax
mov [ebp+aes7z_decoder.bufRest], eax
mov [ebp+aes7z_decoder.NumCyclesPower], eax
mov [ebp+aes7z_decoder.SaltSize], eax
lea edi, [ebp+aes7z_decoder.Salt]
push 8
pop ecx
rep stosd ; zero .Salt and .iv
mov [ebp+streamInfo.fillBuf], aes7z_decoder.fillBuf
; parse parameters
cmp dword [esi-4], eax
jz .parok ; no parameters - OK
lodsb
mov cl, al
and al, 0x3F
mov byte [ebp+aes7z_decoder.NumCyclesPower], al
test cl, 0xC0
jz .parok
test cl, 0x80
setnz byte [ebp+aes7z_decoder.SaltSize]
shr cl, 6
and ecx, 1
cmp dword [esi-1-4], 2
jb return.err
lodsb
mov dl, al
shr al, 4
add byte [ebp+aes7z_decoder.SaltSize], al
and edx, 0xF
add ecx, edx
lea edx, [ecx+2]
push ecx
mov ecx, [ebp+aes7z_decoder.SaltSize]
add edx, ecx
cmp dword [esi-2-4], edx
jb return.err
lea edi, [ebp+aes7z_decoder.Salt]
rep movsb
pop ecx
lea edi, [ebp+aes7z_decoder.iv]
rep movsb
.parok:
test bl, bl
jnz .ret ; if reinitializing - all calculations have been already done
call query_password
jz return.clear
;.CalculateDigest:
mov cl, byte [ebp+aes7z_decoder.NumCyclesPower]
cmp cl, 0x3F
jnz .sha
lea edi, [ebp+aes7z_decoder.Key]
mov ecx, [ebp+aes7z_decoder.SaltSize]
push 32
pop edx
sub edx, ecx
lea esi, [ebp+aes7z_decoder.Salt]
rep movsb
mov ecx, [password_size]
add ecx, ecx
cmp ecx, edx
jbe @f
mov ecx, edx
@@:
sub edx, ecx
mov esi, password_unicode
rep movsb
mov ecx, edx
xor eax, eax
rep stosb
jmp .setkey
.sha:
cmp cl, 32
jb .normal
push 1
shl dword [esp], cl
push 0
jmp @f
.normal:
push 0
push 1
shl dword [esp], cl
@@:
push 0
push 0
call sha256_init
.loop:
lea esi, [ebp+aes7z_decoder.Salt]
mov edx, [ebp+aes7z_decoder.SaltSize]
call sha256_update
mov esi, password_unicode
mov edx, [password_size]
add edx, edx
call sha256_update
mov esi, esp
push 8
pop edx
call sha256_update
mov esi, esp
dec esi
@@:
inc esi
inc byte [esi]
jz @b
sub dword [esp+8], 1
sbb dword [esp+12], 0
mov eax, [esp+8]
or eax, [esp+12]
jnz .loop
lea edi, [ebp+aes7z_decoder.Key]
call sha256_final
add esp, 16
.setkey:
lea esi, [ebp+aes7z_decoder.Key]
push 8
pop edx ; 7z uses 256-bit keys
lea edi, [ebp+aes7z_decoder.nr]
call aes_setkey
.ret:
ret
/programs/fs/kfar/trunk/kfar_arc/7zbranch.inc
0,0 → 1,469
; Branch filters for 7-Zip archives: BCJ and BCJ2.
; Ported from C++ sources of 7-Zip (c) Igor Pavlov.
virtual at 0
bcj_decoder:
.outStream rb streamInfo.size
.inStream dd ?
.inPtr dd ?
.inSize dd ?
.nowPos dd ? ; offset in stream
.prevPos dd ? ; pointer in buffer
.prevMask db ?
.numRest db ?
rw 1
.dwordRest dd ?
.tempSize dd ?
.tempDword dd ?
.size = $
end virtual
 
bcj_get_buf_size:
mov eax, bcj_decoder.size
mov edx, 0x4000
ret
 
bcj_init_decoder:
mov [ebp+streamInfo.fillBuf], bcj_fillBuf
xor edx, edx
mov [ebp+bcj_decoder.inPtr], edx
mov [ebp+bcj_decoder.inSize], edx
mov [ebp+bcj_decoder.prevPos], edx
mov [ebp+bcj_decoder.nowPos], edx
mov [ebp+bcj_decoder.numRest], dl
ret
 
bcj_fillBuf:
add [eax+bcj_decoder.nowPos], ecx
mov ebp, ecx ; save output size
mov esi, [eax+bcj_decoder.inPtr]
mov ebx, [eax+bcj_decoder.inStream]
mov ecx, [eax+bcj_decoder.inSize]
add esi, [ebx+streamInfo.bufPtr]
mov ebx, eax
cmp [eax+bcj_decoder.prevPos], 0
jz @f
add [eax+bcj_decoder.prevPos], edi
@@:
cmp [ebx+bcj_decoder.numRest], 0
jz .mainloop
sub ebp, 1
js .mainloopdone
dec [ebx+bcj_decoder.numRest]
mov eax, [ebx+bcj_decoder.dwordRest]
stosb
shr eax, 8
mov [ebx+bcj_decoder.dwordRest], eax
jmp @b
.mainloop:
sub ebp, 1
js .mainloopdone
sub ecx, 1
js .refill1
.filled1:
lodsb
.filled2:
stosb
cmp al, 0xE8
jz .filter
cmp al, 0xE9
jnz .mainloop
.filter:
and [ebx+bcj_decoder.tempSize], 0
sub ecx, 4
jb .nopos
js .nopos2
lodsd
push eax
.posok:
xor edx, edx
mov eax, edi
sub eax, [ebx+bcj_decoder.prevPos]
cmp eax, 5
ja .maskok
movzx edx, [ebx+bcj_decoder.prevMask]
@@:
and edx, 0x77
add edx, edx
sub eax, 1
jnz @b
.maskok:
mov [ebx+bcj_decoder.prevMask], dl
mov [ebx+bcj_decoder.prevPos], edi
mov al, [esp+3]
add al, 1
cmp al, 2
jae .miss
cmp dl, 0x20
jae .miss2
lea eax, [edx-1]
test eax, edx
jnz .miss2
pop eax
shr edx, 1
push ecx
mov cl, [bcj_kMaskToBitNumber+edx]
iglobal
bcj_kMaskToBitNumber db 24,16,8,8,0,0,0,0
endg
@@:
sub eax, [ebx+bcj_decoder.nowPos]
add eax, [ebx+streamInfo.bufDataLen]
sub eax, edi
sub eax, 4
add eax, [ebx+streamInfo.bufPtr]
cmp cl, 24
jz @f
push eax
shr eax, cl
add al, 1
cmp al, 2
pop eax
jae @f
mov edx, 0x100
shl edx, cl
sub edx, 1
xor eax, edx
jmp @b
@@:
pop ecx
shl eax, 7
sar eax, 7
sub ebp, 4
jb .finalize_dword
stosd
jmp .mainloop
.miss2:
or [ebx+bcj_decoder.prevMask], 10h
.miss:
or [ebx+bcj_decoder.prevMask], 1
cmp [ebx+bcj_decoder.tempSize], 0
jz @f
lea esi, [ebx+bcj_decoder.tempDword]
pop dword [esi]
mov ecx, [ebx+bcj_decoder.tempSize]
jmp .mainloop
@@:
pop eax
sub esi, 4
add ecx, 4
jmp .mainloop
.finalize_dword:
add ebp, 4
mov [ebx+bcj_decoder.numRest], 4
@@:
dec ebp
js .save_dword
stosb
dec [ebx+bcj_decoder.numRest]
shr eax, 8
jmp @b
.save_dword:
mov [ebx+bcj_decoder.dwordRest], eax
.mainloopdone:
mov eax, [ebx+bcj_decoder.prevPos]
test eax, eax
jz .noprev
sub eax, edi
mov [ebx+bcj_decoder.prevPos], eax
.noprev:
mov eax, [ebx+bcj_decoder.inStream]
sub esi, [eax+streamInfo.bufPtr]
mov [ebx+bcj_decoder.inPtr], esi
mov [ebx+bcj_decoder.inSize], ecx
popad
ret
 
.refill1:
cmp ecx, -1
jz .refill0
lodsb
cmp ecx, -4
jnz @f
mov ecx, [ebx+bcj_decoder.inStream]
mov esi, [ecx+streamInfo.bufPtr]
mov ecx, [ecx+streamInfo.bufDataLen]
@@:
jmp .filled2
.refill0:
mov eax, [ebx+bcj_decoder.inStream]
call fillBuf
mov esi, [eax+streamInfo.bufPtr]
mov ecx, [eax+streamInfo.bufDataLen]
sub ecx, 1
js return.err
jmp .filled1
 
.nopos:
mov eax, [ebx+bcj_decoder.inStream]
cmp dword [eax+streamInfo.fullSize+4], 0
jnz .hasdata
push ecx
add ecx, dword [eax+streamInfo.fullSize]
pop ecx
jc .hasdata
add ecx, 4
jmp .mainloop
.hasdata:
mov [ebx+bcj_decoder.tempSize], ecx
push 0
push edi
lea edi, [esp+4]
add ecx, 4
rep movsb
sub esi, ebx
sub esi, 1
cmp esi, bcj_decoder.tempDword+4
jbe @f
call fillBuf
@@:
mov esi, [eax+streamInfo.bufPtr]
mov ecx, [ebx+bcj_decoder.tempSize]
neg ecx
rep movsb
pop edi
mov ecx, [eax+streamInfo.bufDataLen]
add ecx, [ebx+bcj_decoder.tempSize]
cmp [ebx+bcj_decoder.tempSize], -4
jnz .posok
and [ebx+bcj_decoder.tempSize], 0
jmp .posok
.nopos2:
mov eax, [ebx+bcj_decoder.inStream]
add ecx, 4
jmp .hasdata
 
virtual at 0
bcj2_decoder:
.outStream rb streamInfo.size
.mainInStream dd ?
.callStream dd ?
.jumpStream dd ?
.rangeDecoder dd ?
.dwordRest dd ?
.prevByte db ?
.numRest db ?
.bInited db ?
rb 1
.inPtr dd ?
.inSize dd ?
.callPtr dd ?
.jumpPtr dd ?
.callSize dd ?
.jumpSize dd ?
.rangeDecPtr dd ?
.rangeDecSize dd ?
.nowPos dd ?
.range dd ?
.code dd ?
.statusE9Decoder dd ?
.statusJccDecoder dd ?
.statusE8Decoder rd 256
.size = $
end virtual
 
bcj2_get_buf_size:
mov eax, bcj2_decoder.size
mov edx, 0x4000
ret
 
bcj2_init_decoder:
mov [ebp+streamInfo.fillBuf], bcj2_fillBuf
mov eax, lzma_decoder.kBitModelTotal/2
mov ecx, 256+1+1
lea edi, [ebp+bcj2_decoder.statusE9Decoder]
rep stosd
mov dword [ebp+bcj2_decoder.prevByte], ecx
mov [ebp+bcj2_decoder.inSize], ecx
mov [ebp+bcj2_decoder.callSize], ecx
mov [ebp+bcj2_decoder.jumpSize], ecx
mov [ebp+bcj2_decoder.rangeDecSize], ecx
mov [ebp+bcj2_decoder.nowPos], ecx
ret
 
bcj2_fillBuf.init:
mov eax, [eax+bcj2_decoder.rangeDecoder]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
sub edx, 5
jb return.err
mov [ebp+bcj2_decoder.rangeDecSize], edx
mov edx, [eax+streamInfo.bufPtr]
add edx, 5
mov [ebp+bcj2_decoder.rangeDecPtr], edx
mov edx, [edx-4]
bswap edx
mov [ebp+bcj2_decoder.code], edx
or [ebp+bcj2_decoder.range], -1
mov [ebp+bcj2_decoder.bInited], 1
mov eax, ebp
jmp bcj2_fillBuf.inited
 
bcj2_fillBuf:
mov ebp, eax
cmp [eax+bcj2_decoder.bInited], 0
jz .init
.inited:
add [eax+bcj2_decoder.nowPos], ecx
mov esi, [eax+bcj2_decoder.inPtr]
@@:
cmp [ebp+bcj2_decoder.numRest], 0
jz .mainloop
sub ecx, 1
js .mainloopdone
dec [ebp+bcj2_decoder.numRest]
mov eax, [ebp+bcj2_decoder.dwordRest]
stosb
mov [ebp+bcj2_decoder.prevByte], al
shr eax, 8
mov [ebp+bcj2_decoder.dwordRest], eax
jmp @b
.mainloop:
sub ecx, 1
js .mainloopdone
sub [ebp+bcj2_decoder.inSize], 1
js .refill1
.filled1:
lodsb
stosb
cmp al, 0xE8
jz .e8
cmp al, 0xE9
jz .e9
cmp [ebp+bcj2_decoder.prevByte], 0xF
mov [ebp+bcj2_decoder.prevByte], al
jnz .mainloop
and al, 0xF0
cmp al, 0x80
jnz .mainloop
.jcc:
lea eax, [ebp+bcj2_decoder.statusJccDecoder]
call .RangeDecoderBitDecode
jnc .mainloop
jmp .getptrj
.e8:
movzx eax, al
xchg al, [ebp+bcj2_decoder.prevByte]
lea eax, [ebp+bcj2_decoder.statusE8Decoder+eax*4]
call .RangeDecoderBitDecode
jnc .mainloop
lea eax, [ebp+bcj2_decoder.callPtr]
jmp .getptr
.e9:
mov [ebp+bcj2_decoder.prevByte], al
lea eax, [ebp+bcj2_decoder.statusE9Decoder]
call .RangeDecoderBitDecode
jnc .mainloop
.getptrj:
lea eax, [ebp+bcj2_decoder.jumpPtr]
.getptr:
sub dword [eax+8], 4
js .refill2
.filled2:
add dword [eax], 4
mov eax, [eax]
mov eax, [eax-4]
bswap eax
sub eax, [ebp+bcj2_decoder.nowPos]
add eax, [ebp+streamInfo.bufDataLen]
sub eax, edi
sub eax, 4
add eax, [ebp+streamInfo.bufPtr]
sub ecx, 4
jb .finalize_dword
stosd
shr eax, 24
mov [ebp+bcj2_decoder.prevByte], al
jmp .mainloop
.finalize_dword:
add ecx, 4
mov [ebp+bcj2_decoder.numRest], 4
@@:
dec ecx
js .save_dword
stosb
dec [ebp+bcj2_decoder.numRest]
shr eax, 8
jmp @b
.save_dword:
mov [ebp+bcj2_decoder.dwordRest], eax
.mainloopdone:
mov [ebp+bcj2_decoder.inPtr], esi
popad
ret
 
.refill1:
mov eax, [ebp+bcj2_decoder.mainInStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
dec edx
js return.err
mov [ebp+bcj2_decoder.inSize], edx
mov esi, [eax+streamInfo.bufPtr]
jmp .filled1
 
.refill2:
push eax
mov eax, [eax-bcj2_decoder.callPtr+bcj2_decoder.callStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
sub edx, 4
js return.err
push [eax+streamInfo.bufPtr]
mov eax, [esp+4]
pop dword [eax]
pop eax
mov [eax+8], edx
jmp .filled2
 
.refill3:
push eax
mov eax, [ebp+bcj2_decoder.rangeDecoder]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
dec edx
js return.err
mov [ebp+bcj2_decoder.rangeDecSize], edx
mov edx, [eax+streamInfo.bufPtr]
mov [ebp+bcj2_decoder.rangeDecPtr], edx
pop eax
jmp .filled3
 
.RangeDecoderBitDecode:
; in: eax->prob
; out: CF=bit; destroys eax,edx
mov edx, [ebp+bcj2_decoder.range]
shr edx, lzma_decoder.kNumBitModelTotalBits
imul edx, [eax]
cmp [ebp+bcj2_decoder.code], edx
jae .ae
mov [ebp+bcj2_decoder.range], edx
mov edx, lzma_decoder.kBitModelTotal
sub edx, [eax]
shr edx, lzma_decoder.kNumMoveBits
add [eax], edx
clc
.n:
lahf
cmp [ebp+bcj2_decoder.range], lzma_decoder.kTopValue
jae @f
shl [ebp+bcj2_decoder.range], 8
shl [ebp+bcj2_decoder.code], 8
dec [ebp+bcj2_decoder.rangeDecSize]
js .refill3
.filled3:
mov edx, [ebp+bcj2_decoder.rangeDecPtr]
mov al, [edx]
add edx, 1
mov [ebp+bcj2_decoder.rangeDecPtr], edx
mov byte [ebp+bcj2_decoder.code], al
@@:
sahf
ret
.ae:
sub [ebp+bcj2_decoder.range], edx
sub [ebp+bcj2_decoder.code], edx
mov edx, [eax]
shr edx, lzma_decoder.kNumMoveBits
sub [eax], edx
stc
jmp .n
/programs/fs/kfar/trunk/kfar_arc/aes.inc
0,0 → 1,274
; Implementation of AES crypto algorithm.
; Buffer size is 0x10 bytes (128 bits), key size is not fixed.
; Written by diamond in 2007.
uglobal
aes.pow_table rb 256 ; pow[a] = 3^a
aes.log_table rb 256 ; log[3^a] = a
aes.sbox rb 256 ; ShiftBytes(a)
aes.sbox_rev rb 256 ; ShiftBytes^{-1}(a)
aes.mctable rd 256 ; MixColumns(ShiftBytes(a,0,0,0))
aes.mcrtable rd 256 ; MixColumns^{-1}(a,0,0,0)
endg
 
init_aes:
; Byte values in SubBytes transform are interpreted as items of
; GF(2^8) \cong F_2[x]/(x^8+x^4+x^3+x+1)F_2[x].
; x+1 is primitive item in this field.
xor ebx, ebx
push 1
pop eax
.1:
mov [aes.pow_table+ebx], al
mov [aes.log_table+eax], bl
; Multiplication by x+1...
mov cl, al ; save value
; ...multiply by x with mod (x^8+x^4+x^3+x+1) = 0x11B...
add al, al
jnc @f
xor al, 0x1B
@@:
; ...and add operand
xor al, cl
inc bl
jnz .1
; generate table for SubBytes transform
mov [aes.sbox+0], 0x63
mov [aes.sbox_rev+0x63], bl
inc ebx
.2:
; calculate inverse in GF(2^8)
mov al, [aes.log_table+ebx]
xor al, 0xFF ; equivalent to "al = 0xFF - al"
mov cl, [aes.pow_table+eax]
; linear transform of byte as vector over F_2
mov al, cl
rol cl, 1
xor al, cl
rol cl, 1
xor al, cl
rol cl, 1
xor al, cl
rol cl, 1
xor al, cl
xor al, 0x63
mov [aes.sbox+ebx], al
mov [aes.sbox_rev+eax], bl
inc bl
jnz .2
; generate table for SubBytes + MixColumn transforms
.3:
mov al, [aes.sbox+ebx] ; SubBytes transform
mov cl, al
add cl, cl
jnc @f
xor cl, 0x1B
@@:
mov byte [aes.mctable+ebx*4], cl ; low byte of MixColumn(a,0,0,0)
mov byte [aes.mctable+ebx*4+1], al
mov byte [aes.mctable+ebx*4+2], al
xor cl, al
mov byte [aes.mctable+ebx*4+3], cl ; high byte of MixColumn(a,0,0,0)
inc bl
jnz .3
; generate table for reverse MixColumn transform
mov dword [aes.mcrtable+0], ebx
inc ebx
.4:
; log_table[9]=0xC7, log_table[0xB]=0x68, log_table[0xD]=0xEE, log_table[0xE]=0xDF
mov cl, [aes.log_table+ebx]
mov al, cl
add al, 0xDF
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4], al
mov al, cl
add al, 0xC7
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4+1], al
mov al, cl
add al, 0xEE
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4+2], al
mov al, cl
add al, 0x68
adc al, 0
mov al, [aes.pow_table+eax]
mov byte [aes.mcrtable+ebx*4+3], al
inc bl
jnz .4
ret
 
aes_setkey:
; in: esi->key, edx=key size in dwords, edi->AES data struc
lea eax, [edx+6] ; calc number of rounds (buffer size=4)
stosd
shl eax, 4
lea ebx, [edi+eax+16]
mov ecx, edx
rep movsd
push ebx
mov bl, 1
.0:
push 4
pop ecx
@@:
movzx esi, byte [edi-5+ecx]
mov al, [aes.sbox+esi]
rol eax, 8
loop @b
ror eax, 16
mov esi, edx
neg esi
xor eax, [edi+esi*4]
xor al, bl
add bl, bl
jnc @f
xor bl, 0x1B
@@:
stosd
lea ecx, [edx-1]
.1:
cmp edi, [esp]
jz .ret
cmp edx, 8
jnz @f
cmp ecx, 4
jnz @f
push eax
movzx eax, al
mov al, [aes.sbox+eax]
mov [esp], al
mov al, byte [esp+1]
mov al, [aes.sbox+eax]
mov [esp+1], al
mov al, byte [esp+2]
mov al, [aes.sbox+eax]
mov [esp+2], al
mov al, byte [esp+3]
mov al, [aes.sbox+eax]
mov [esp+3], al
pop eax
@@:
xor eax, [edi+esi*4]
stosd
loop .1
cmp edi, [esp]
jnz .0
.ret:
pop eax
ret
 
aes_decode:
; in: esi->in, ebx->out, edi->AES state
push ebx ebp
push dword [esi+12]
push dword [esi+8]
push dword [esi+4]
push dword [esi]
mov esi, esp
; reverse final round
mov ebp, [edi] ; number of rounds
mov ecx, ebp
shl ecx, 4
lea edi, [edi+ecx+4] ; edi->last round key
; load buffer into registers
mov eax, [esi]
mov ebx, [esi+4]
mov ecx, [esi+8]
mov edx, [esi+12]
; (AddRoundKey)
xor eax, [edi]
xor ebx, [edi+4]
xor ecx, [edi+8]
xor edx, [edi+12]
; (ShiftRows)
.loop0:
xchg ch, dh
xchg bh, ch
xchg ah, bh
rol eax, 16
rol ebx, 16
rol ecx, 16
rol edx, 16
xchg al, cl
xchg bl, dl
xchg ah, bh
xchg bh, ch
xchg ch, dh
rol eax, 16
rol ebx, 16
rol ecx, 16
rol edx, 16
; (SubBytes)
mov [esi], eax
mov [esi+4], ebx
mov [esi+8], ecx
mov [esi+12], edx
mov ecx, 16
@@:
movzx eax, byte [esi]
mov al, [aes.sbox_rev+eax]
mov byte [esi], al
add esi, 1
sub ecx, 1
jnz @b
sub esi, 16
sub edi, 16
; reverse normal rounds
sub ebp, 1
jz .done
mov eax, [esi]
mov ebx, [esi+4]
mov ecx, [esi+8]
mov edx, [esi+12]
push esi edi
; (AddRoundKey)
xor eax, [edi]
xor ebx, [edi+4]
xor ecx, [edi+8]
xor edx, [edi+12]
; (MixColumns)
macro mix_reg reg {
movzx esi, reg#l
mov edi, [aes.mcrtable+esi*4]
movzx esi, reg#h
rol e#reg#x, 16
mov esi, [aes.mcrtable+esi*4]
rol esi, 8
xor edi, esi
movzx esi, reg#l
mov esi, [aes.mcrtable+esi*4]
rol esi, 16
xor edi, esi
movzx esi, reg#h
mov esi, [aes.mcrtable+esi*4]
ror esi, 8
xor edi, esi
mov e#reg#x, edi
}
mix_reg a
mix_reg b
mix_reg c
mix_reg d
purge mix_reg
pop edi esi
jmp .loop0
.done:
; (AddRoundKey)
mov esi, [esp+20]
pop eax
xor eax, [edi]
mov [esi], eax
pop eax
xor eax, [edi+4]
mov [esi+4], eax
pop eax
xor eax, [edi+8]
mov [esi+8], eax
pop eax
xor eax, [edi+12]
mov [esi+12], eax
pop ebp ebx
ret
/programs/fs/kfar/trunk/kfar_arc/crc.inc
0,0 → 1,32
init_crc_table:
xor edx, edx
mov edi, crc_table
.1:
mov ecx, 8
mov eax, edx
.2:
shr eax, 1
jnc @f
xor eax, 0xEDB88320
@@:
loop .2
stosd
inc dl
jnz .1
ret
 
crc:
; in: ecx=size, esi->buffer
; out: eax=crc
or eax, -1
jecxz .end
.loop:
movzx edx, al
xor dl, byte [esi]
inc esi
shr eax, 8
xor eax, [crc_table+edx*4]
loop .loop
.end:
xor eax, -1
ret
/programs/fs/kfar/trunk/kfar_arc/kfar_arc.asm
0,0 → 1,1075
;
; project name: KFar_Arc - plugin for KFar, which supports various archives
; target platform: KolibriOS
; compiler: FASM 1.67.14
; version: 0.1
; last update: 2007-07-11 (Jul 11, 2007)
; minimal KFar version: 0.4
; minimal kernel: no limit
;
; author: Diamond
; email: diamondz@land.ru
; web: http://diamondz.land.ru
;
 
; standard start of Kolibri dynamic library
format MS COFF
public EXPORTS
 
section '.flat' code readable align 16
 
; include auxiliary procedures
include 'kglobals.inc' ; iglobal/uglobal
include 'lang.inc' ; define language for localized strings
include 'crc.inc' ; CRC32 calculation
include 'sha256.inc' ; SHA-256 hash algorithm
include 'aes.inc' ; AES crypto algorithm
; include main code for archives loading
include '7z.inc' ; *.7z
include 'lzma.inc' ; LZMA-decoder for *.7z
include 'ppmd.inc' ; PPMD-decoder for *.7z
include '7zbranch.inc' ; branch filters for *.7z
include '7zaes.inc' ; AES cryptor for *.7z
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; Interface for KFar ;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
virtual at 0
kfar_info_struc:
.lStructSize dd ?
.kfar_ver dd ?
.open dd ?
.read dd ?
.write dd ?
.seek dd ?
.flush dd ?
.filesize dd ?
.close dd ?
.pgalloc dd ?
.pgrealloc dd ?
.pgfree dd ?
.getfreemem dd ?
.pgalloc2 dd ?
.pgrealloc2 dd ?
.pgfree2 dd ?
.menu dd ?
.menu_centered_in dd ?
.DialogBox dd ?
.SayErr dd ?
.Message dd ?
.cur_console_size dd ?
end virtual
 
; int __stdcall plugin_load(kfar_info* info);
; Initialization of plugin + Save used KFar functions.
plugin_load:
mov eax, [esp+4]
mov [kfar_info], eax
push [eax+kfar_info_struc.read]
pop [read]
push [eax+kfar_info_struc.seek]
pop [seek]
push [eax+kfar_info_struc.close]
pop [close]
lea esi, [eax+kfar_info_struc.DialogBox]
mov edi, DialogBox
movsd
movsd
movsd
movsd
lea esi, [eax+kfar_info_struc.pgalloc]
mov edi, pgalloc
movsd
movsd
movsd
movsd
call init_crc_table
call init_aes
call init_ppmd
xor eax, eax ; success
ret 4
 
; HANDLE __stdcall OpenFilePlugin(HANDLE basefile, const char* name,
; const void* attr, const void* data, int datasize);
; This function is called when user presses Enter (or Ctrl+PgDn) on file.
; Plugin tests whether given file is of supported type
; and if so, loads information and returns
; handle to be used in subsequent calls to ReadFolder, SetFolder and so on.
OpenFilePlugin:
mov [bPasswordDefined], 0
mov esi, [esp+16]
mov ebp, [esp+4]
; test for 7z archive
cmp dword [esp+20], 20h ; minimal size of 7z archive is 20h bytes
jb .no_7z
cmp word [esi], '7z' ; signature, part 1
jnz .no_7z
cmp dword [esi+2], 0x1C27AFBC ; signature, part 2
jnz .no_7z
call open_7z
ret 20
.no_7z:
xor eax, eax
ret 20
 
; Handle of plugin in kfar_arc is as follow:
virtual at 0
handle_common:
.type dd ?
.root.subfolders dd ?
.root.subfolders.end dd ?
.root.subfiles dd ?
.root.subfiles.end dd ?
.root.NumSubItems dd ?
; ... some plugin-specific data follows ...
end virtual
 
; and for each archive item there is one file info structure, which begins as follow:
virtual at 0
file_common:
.fullname dd ? ; pointer to cp866 string
.name dd ? ; name without path (end of .fullname)
.namelen dd ? ; strlen(.name)
.bIsDirectory db ?
.bPseudoFolder db ?
rb 2
.parent dd ? ; pointer to parent directory record
.subfolders dd ? ; head of L2-list of subfolders [for folders]
.subfolders.end dd ?
.subfiles dd ? ; head of L2-list of files [for folders]
.subfiles.end dd ?
.NumSubItems dd ?
.next dd ? ; next item in list of subfolders/files
.prev dd ? ; previous item in list of subfolders/files
end virtual
 
; void __stdcall ClosePlugin(HANDLE hPlugin);
; This function frees all resources allocated in OpenFilePlugin.
ClosePlugin:
mov eax, [esp+4] ; get hPlugin
mov eax, [eax] ; hPlugin is pointer to internal data structure
; first dword is archive type (type_xxx constants)
dec eax ; types start from 1
jmp dword [ClosePluginTable+eax*4]
 
; int __stdcall ReadFolder(HANDLE hPlugin,
; unsigned dirinfo_start, unsigned dirinfo_size, void* dirdata);
ReadFolder:
mov eax, [esp+4]
mov eax, [eax]
dec eax
jmp dword [ReadFolderTable+eax*4]
 
; bool __stdcall SetFolder(HANDLE hPlugin,
; const char* relative_path, const char* absolute_path);
SetFolder:
mov eax, [esp+4]
mov eax, [eax]
dec eax
jmp dword [SetFolderTable+eax*4]
 
; void __stdcall GetFiles(HANDLE hPlugin, int NumItems, void* items[],
; void* addfile, void* adddir);
; bool __stdcall addfile(const char* name, void* bdfe_info, HANDLE hFile);
; bool __stdcall adddir(const char* name, void* bdfe_info);
GetFiles:
mov ebp, [esp+4]
mov eax, [ebp]
dec eax
jmp dword [GetFilesTable+eax*4]
 
; void __stdcall GetOpenPluginInfo(HANDLE hPlugin, OpenPluginInfo* info);
GetOpenPluginInfo:
mov eax, [esp+8] ; get info ptr
mov byte [eax], 3 ; flags: add non-existing '..' entry automatically
; use GetFiles for copying
ret 8
 
; int __stdcall getattr(HANDLE hPlugin, const char* filename, void* info);
mygetattr:
call lookup_file_name
test eax, eax
jz @f
mov edx, [ebp]
dec edx
mov edi, [esp+12] ; info ptr
call dword [getattrTable+edx*4]
xor eax, eax
ret 12
@@:
mov al, 5 ; ERROR_FILE_NOT_FOUND
ret 12
 
; HANDLE __stdcall open(HANDLE hPlugin, const char* filename, int mode);
myopen:
call lookup_file_name
test eax, eax
jz @f
mov edx, [ebp]
dec edx
mov edi, [esp+12] ; mode
call dword [openTable+edx*4]
@@:
ret 12
 
; unsigned __stdcall read(HANDLE hFile, void* buf, unsigned size);
myread:
mov ebx, [esp+4]
mov eax, [ebx]
jmp dword [readTable+eax*4]
 
; void __stdcall setpos(HANDLE hFile, __int64 pos);
mysetpos:
mov ebx, [esp+4]
mov eax, [ebx]
jmp dword [setposTable+eax*4]
 
; void __stdcall close(HANDLE hFile);
myclose:
mov ebx, [esp+4]
mov eax, [ebx]
jmp dword [closeTable+eax*4]
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;; Auxiliary procedures ;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; return.err and return.clear are labels to jmp if something is invalid
; the caller must previously define [_esp], [_ebp] and [error_proc], [clear_proc]
return.err:
mov esp, [_esp]
mov ebp, [_ebp]
jmp [error_proc]
return.clear:
mov esp, [_esp]
mov ebp, [_ebp]
jmp [clear_proc]
 
; data for following routine
iglobal
align 4
_24 dd 24
_60 dd 60
_10000000 dd 10000000
days400year dd 365*400+100-4+1
days100year dd 365*100+25-1
days4year dd 365*4+1
days1year dd 365
months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
_400 dd 400
_100 dd 100
endg
 
; Convert QWORD FILETIME to BDFE format.
ntfs_datetime_to_bdfe:
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
push eax
mov eax, edx
xor edx, edx
div [_10000000]
xchg eax, [esp]
div [_10000000]
pop edx
; edx:eax = number of seconds since January 1, 1601
push eax
mov eax, edx
xor edx, edx
div [_60]
xchg eax, [esp]
div [_60]
mov [edi], dl
pop edx
; edx:eax = number of minutes
div [_60]
mov [edi+1], dl
; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32)
xor edx, edx
div [_24]
mov [edi+2], dl
mov [edi+3], byte 0
; eax = number of days since January 1, 1601
xor edx, edx
div [days400year]
imul eax, 400
add eax, 1601
mov [edi+6], ax
mov eax, edx
xor edx, edx
div [days100year]
cmp al, 4
jnz @f
dec eax
add edx, [days100year]
@@:
imul eax, 100
add [edi+6], ax
mov eax, edx
xor edx, edx
div [days4year]
shl eax, 2
add [edi+6], ax
mov eax, edx
xor edx, edx
div [days1year]
cmp al, 4
jnz @f
dec eax
add edx, [days1year]
@@:
add [edi+6], ax
push esi edx
mov esi, months
movzx eax, word [edi+6]
test al, 3
jnz .noleap
xor edx, edx
push eax
div [_400]
pop eax
test edx, edx
jz .leap
xor edx, edx
div [_100]
test edx, edx
jz .noleap
.leap:
mov esi, months2
.noleap:
pop edx
xor eax, eax
inc eax
@@:
sub edx, [esi]
jb @f
add esi, 4
inc eax
jmp @b
@@:
add edx, [esi]
pop esi
inc edx
mov [edi+4], dl
mov [edi+5], al
add edi, 8
ret
 
; By given array of files information, initialize links between them
; ("[folder] contains [item]" relations).
; Information structure must be compatible with 'file_common'.
; Size of information structure is in [esp+4].
init_file_links:
; in: edx->file infos, ebx = number of files, [esp+4] = size,
; edi->{dd root.subfolders, dd root.subfolders.end,
; dd root.subfiles, dd root.subfiles.end, dd root.NumItems}
xor eax, eax
mov [.free], eax
push edi
stosd
stosd
stosd
stosd
stosd
pop edi
; Loop through all files
.mainloop:
dec ebx
js .mainloopdone
; Parse file name
; esi->current character in name
; dword [esp] = start of current component in file name
; ecx->{dd curdir.subfolders, dd curdir.subfolders.end,
; dd curdir.subfiles, dd curdir.subfiles.end}
mov esi, [edx+file_common.fullname]
mov ecx, edi
.parseloop:
push esi
.parsename:
lodsb
test al, al
jz @f
cmp al, '/'
jnz .parsename
@@:
; we have found next component of current name; look for it in current directory
sub esi, [esp]
dec esi ; esi = strlen(component)
cmp esi, 259
jbe @f
push ContinueBtn
push 1
push aNameTooLong_ptr
push 1
call [SayErr]
jmp return.clear
@@:
push ecx
mov eax, [ecx] ; eax->subfolders list
mov ecx, esi
.scansubfolders:
test eax, eax
jz .nofolder
add eax, [hOut]
cmp [eax+file_common.namelen], ecx
jnz .scancont
mov esi, [esp+4]
push ecx edi
mov edi, [eax+file_common.name]
repz cmpsb
pop edi ecx
jz .subfound
.scancont:
mov eax, [eax+file_common.next]
jmp .scansubfolders
.subfound:
; found subfolder, set it as current and continue parsing name
add [esp+4], ecx
pop ecx
lea ecx, [eax+file_common.subfolders]
pop esi
lodsb
test al, al
jnz .parseloop
; that was the last component of the name, and we have found subfolder
; so found subfolder is a virtual subfolder and must be replaced with current
; name
mov eax, [ecx-file_common.subfolders+file_common.namelen]
mov [edx+file_common.namelen], eax
sub esi, eax
dec esi
mov [edx+file_common.name], esi
sub edx, [hOut] ; convert pointer to relative
; replace item in L2-list
mov eax, [ecx-file_common.subfolders+file_common.prev]
test eax, eax
jnz .1
mov eax, [ecx-file_common.subfolders+file_common.parent]
sub eax, file_common.next - file_common.subfolders
jnc .1
lea eax, [edi-file_common.next]
jmp .2
.1:
add eax, [hOut]
.2:
mov [eax+file_common.next], edx
mov eax, [ecx-file_common.subfolders+file_common.next]
test eax, eax
jnz .3
mov eax, [ecx-file_common.subfolders+file_common.parent]
sub eax, file_common.prev - file_common.subfolders.end
jnc .3
lea eax, [edi-file_common.prev+4]
jmp .4
.3:
add eax, [hOut]
.4:
mov [eax+file_common.prev], edx
; correct parent links in childrens
mov eax, [ecx]
@@:
test eax, eax
jz @f
add eax, [hOut]
mov [eax+file_common.parent], edx
mov eax, [eax+file_common.next]
jmp @b
@@:
mov eax, [ecx+8]
@@:
test eax, eax
jz @f
add eax, [hOut]
mov [eax+file_common.parent], edx
mov eax, [eax+file_common.next]
jmp @b
@@:
add edx, [hOut]
; set children links
mov eax, [ecx]
mov [edx+file_common.subfolders], eax
mov eax, [ecx+4]
mov [edx+file_common.subfolders.end], eax
mov eax, [ecx+8]
mov [edx+file_common.subfiles], eax
mov eax, [ecx+12]
mov [edx+file_common.subfiles.end], eax
mov eax, [ecx+16]
mov [edx+file_common.NumSubItems], eax
; set prev/next links
mov eax, [ecx-file_common.subfolders+file_common.next]
mov [edx+file_common.next], eax
mov eax, [ecx-file_common.subfolders+file_common.prev]
mov [edx+file_common.prev], eax
; add old item to list of free items
uglobal
align 4
init_file_links.free dd ?
endg
sub ecx, file_common.subfolders
mov eax, [.free]
mov [ecx], eax
sub ecx, [hOut]
mov [.free], ecx
jmp .mainloopcont
.nofolder:
mov eax, edx
mov esi, [esp+4]
cmp byte [esi+ecx], 0
jz .newitem
; the current item is as 'dir1/item1' and 'dir1' has not been found
; allocate virtual subfolder 'dir1'
mov eax, [init_file_links.free]
test eax, eax
jz .realloc
add eax, [hOut]
push dword [eax]
pop [init_file_links.free]
jmp .allocated
.realloc:
; there is no free space, so reallocate [hOut] block
mov eax, [hOut]
sub [esp], eax ; make pointers relative
sub edx, eax
sub edi, eax
push ecx
mov ecx, [hOut.allocated]
add ecx, [esp+12+4]
mov [hOut.allocated], ecx
push ecx
and ecx, 0xFFF
cmp ecx, [esp+16+4]
pop ecx
ja @f
push edx
mov edx, eax
call [pgrealloc]
pop edx
test eax, eax
jnz @f
mov ecx, [hOut]
call [pgfree]
mov esp, [_esp]
or eax, -1
ret
@@:
pop ecx
mov [hOut], eax
add [esp], eax ; make pointers absolute
add edx, eax
add edi, eax
add eax, [hOut.allocated]
sub eax, [esp+8+4]
.allocated:
; eax -> new item
mov [eax+file_common.bIsDirectory], 1
mov [eax+file_common.bPseudoFolder], 1
.newitem:
mov [eax+file_common.namelen], ecx
pop ecx
pop esi
; ecx = parent item, eax = current item
mov [eax+file_common.name], esi
inc dword [ecx+16] ; new item in parent folder
push ecx
; add new item to end of L2-list
and [eax+file_common.next], 0
cmp [eax+file_common.bIsDirectory], 0
jnz @f
add ecx, 8
@@:
push eax
sub eax, [hOut]
cmp dword [ecx], 0
jnz @f
mov [ecx], eax
@@:
xchg eax, [ecx+4]
xchg eax, ecx
pop eax
mov [eax+file_common.prev], ecx
jecxz @f
add ecx, [hOut]
sub eax, [hOut]
mov [ecx+file_common.next], eax
add eax, [hOut]
@@:
pop ecx
; set parent link
and [eax+file_common.parent], 0
cmp ecx, edi
jz @f
sub ecx, file_common.subfolders
sub ecx, [hOut]
mov [eax+file_common.parent], ecx
@@:
; set current directory to current item
lea ecx, [eax+file_common.subfolders]
; if that was not last component, continue parse name
add esi, [eax+file_common.namelen]
lodsb
test al, al
jnz .parseloop
.mainloopcont:
; continue main loop
add edx, [esp+4]
jmp .mainloop
.mainloopdone:
; Loop done.
ret 4
 
; This subroutine is called by getattr and open.
; This subroutine looks for file name and returns NULL or pointer to file info record.
lookup_file_name:
mov ebp, [esp+8] ; hPlugin
mov esi, [esp+12] ; filename
lea edi, [ebp+handle_common.root.subfolders]
xor eax, eax
; KFar operates with absolute names, skip first '/'
cmp byte [esi], '/'
jnz .notfound
inc esi
.mainloop:
; get next component of name
push -1
pop ecx
@@:
inc ecx
cmp byte [esi+ecx], '/'
jz @f
cmp byte [esi+ecx], 0
jnz @b
@@:
; esi->component, ecx=length
; scan for required item in subfolders list
push -1
mov eax, [edi] ; .subfolders
.scan1:
test eax, eax
jz .notfound1
add eax, ebp
cmp [eax+file_common.namelen], ecx
jnz .cont1
push ecx esi edi
mov edi, [eax+file_common.name]
repz cmpsb
pop edi esi ecx
jz .found1
.cont1:
mov eax, [eax+file_common.next]
jmp .scan1
.notfound1:
pop edx
; if this is last component in file name, scan in subfiles list
cmp byte [esi+ecx], al
jnz .notfound
inc edx
jnz .notfound
mov eax, [edi+8] ; .subfiles
push edx
jmp .scan1
.found1:
pop edi
; item is found, go to next component
lea edi, [eax+file_common.subfolders]
lea esi, [esi+ecx+1]
cmp byte [esi-1], 0
jnz .mainloop
; this was the last component
.notfound:
ret
 
; Memory streams handling.
; Archive handlers create memory stream for small files:
; size of which is not greater than (free RAM size)/4 and
; not greater than following constant...
;LIMIT_FOR_MEM_STREAM = 2*1024*1024
; ...if it is defined. Now the definition is commented:
; if user has many physical memory, why not to use it?
 
virtual at 0
mem_stream:
.type dd ? ; type_mem_stream
.size dd ?
.pos dd ?
.buf:
end virtual
 
; unsigned __stdcall read(ebx = HANDLE hFile, void* buf, unsigned size);
read_mem_stream:
mov eax, [esp+12]
mov ecx, [ebx+mem_stream.size]
sub ecx, [ebx+mem_stream.pos]
jnc @f
xor ecx, ecx
@@:
cmp eax, ecx
jb @f
mov eax, ecx
@@:
mov ecx, eax
lea esi, [ebx+mem_stream.buf]
add esi, [ebx+mem_stream.pos]
add [ebx+mem_stream.pos], eax
mov edi, [esp+8]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
ret 12
 
; void __stdcall setpos(ebx = HANDLE hFile, __int64 pos);
setpos_mem_stream:
mov eax, [esp+8]
mov [ebx+mem_stream.pos], eax
ret 12
 
; void __stdcall close(ebx = HANDLE hFile);
close_mem_stream:
mov ecx, ebx
call [pgfree]
ret 4
 
; Allocate handle for file
; esi -> handle table, ecx = size of handle
alloc_handle:
; Handle table is L2-list of allocated pages.
; Scan for free entry
mov edx, esi
@@:
mov edx, [edx]
cmp edx, esi
jz .alloc_new
mov eax, [edx+8] ; head of L1-list of free entries
test eax, eax ; has free entry?
jz @b
; we have found allocated page with free entry; allocate entry and return
inc dword [edx+12] ; number of busy entries
push dword [eax]
pop dword [edx+8]
.ret:
ret
.alloc_new:
; no free pages; get new page and initialize
push ecx
mov ecx, 0x1000
call [pgalloc]
pop ecx
test eax, eax
jz .ret
; insert new page to start of L2-list
mov edx, [esi]
mov [eax], edx
mov [esi], eax
mov [eax+4], esi
mov [edx+4], eax
mov dword [eax+12], 1 ; 1 allocated entry
; initialize list of free entries
lea edx, [eax+16]
push edx ; save return value
add edx, ecx
mov [eax+8], edx
add eax, 0x1000
@@:
mov esi, edx
add edx, ecx
mov [esi], edx
cmp edx, eax
jb @b
and dword [esi], 0
pop eax
ret
 
; Free handle allocated in previous procedure
; esi = handle
free_handle:
mov ecx, esi
and ecx, not 0xFFF ; get page
; add entry to head of L1-list of free entries
mov eax, [ecx+8]
mov [esi], eax
mov [ecx+8], esi
dec dword [ecx+12] ; decrement number of allocated entries
jnz .ret
; delete page from common L2-list
mov eax, [ecx]
mov edx, [ecx+4]
mov [eax+4], edx
mov [edx], eax
; free page
call [pgfree]
.ret:
ret
 
; Ask user to enter password.
; Out: ZF set <=> user pressed Esc
; 'password_ansi', 'password_unicode', 'password_size' filled
query_password:
cmp [bPasswordDefined], 0
jnz .ret
mov edi, password_data
mov eax, password_maxlen
stosd ; maximum length
xor eax, eax
stosd ; start of visible part
stosd ; position of cursor
stosb ; initial state: empty string
mov eax, [cur_console_size]
mov eax, [eax] ; get current console width
sub eax, 12
mov edi, password_dlg
mov [edi+password_dlg.width-password_dlg], eax
dec eax
dec eax
mov [edi+password_dlg.width1-password_dlg], eax
mov [edi+password_dlg.width2-password_dlg], eax
push edi
call [DialogBox]
inc eax
jz .ret
; convert ANSI-cp866 to UNICODE string; also calculate 'password_size'
mov esi, password_ansi
mov edi, password_unicode
or [password_size], -1
.cvt:
inc [password_size]
lodsb
mov ah, 0
; 0x00-0x7F - trivial map
cmp al, 0x80
jb .symb
; 0x80-0xAF -> 0x410-0x43F
cmp al, 0xB0
jae @f
add ax, 0x410-0x80
jmp .symb
@@:
; 0xE0-0xEF -> 0x440-0x44F
cmp al, 0xE0
jb .unk
cmp al, 0xF0
jae @f
add ax, 0x440-0xE0
jmp .symb
@@:
; 0xF0 -> 0x401
; 0xF1 -> 0x451
cmp al, 'ð'
jz .yo1
cmp al, 'ñ'
jz .yo2
.unk:
mov al, '_'
jmp .symb
.yo1:
mov ax, 0x401
jmp .symb
.yo2:
mov ax, 0x451
.symb:
stosw
test al, al
jnz .cvt
inc [bPasswordDefined] ; clears ZF flag
.ret:
ret
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;; Initialized data ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; export table
align 4
EXPORTS:
dd aVersion, 1
dd aPluginLoad, plugin_load
dd aOpenFilePlugin,OpenFilePlugin
dd aClosePlugin, ClosePlugin
dd aReadFolder, ReadFolder
dd aSetFolder, SetFolder
dd aGetFiles, GetFiles
dd aGetOpenPluginInfo, GetOpenPluginInfo
dd aGetattr, mygetattr
dd aOpen, myopen
dd aRead, myread
dd aSetpos, mysetpos
dd aClose, myclose
dd 0
 
; exported names
aVersion db 'version',0
aPluginLoad db 'plugin_load',0
aOpenFilePlugin db 'OpenFilePlugin',0
aClosePlugin db 'ClosePlugin',0
aReadFolder db 'ReadFolder',0
aSetFolder db 'SetFolder',0
aGetFiles db 'GetFiles',0
aGetOpenPluginInfo db 'GetOpenPluginInfo',0
aGetattr db 'getattr',0
aOpen db 'open',0
aRead db 'read',0
aSetpos db 'setpos',0
aClose db 'close',0
 
; common strings
if lang eq ru
aContinue db 'à®¤®«¦¨âì',0
aCancel db 'Žâ¬¥­ ',0
aHeaderError db 'Žè¨¡ª  ¢ § £®«®¢ª¥  à娢 ',0
aReadError db 'Žè¨¡ª  ç⥭¨ï',0
aNoFreeRam db '¥¤®áâ â®ç­® ᢮¡®¤­®© ®¯¥à â¨¢­®© ¯ ¬ïâ¨',0
aEncodingProblem db 'à®¡«¥¬  á ª®¤¨à®¢ª®©',0
aEncodingProblem_str db 'ˆ¬¥­  ­¥ª®â®àëå ä ©«®¢ ¢  à娢¥ ᮤ¥à¦ â ᨬ¢®«ë,',0
.2 db '­¥ ¯à¥¤áâ ¢¨¬ë¥ ¢ ª®¤¨à®¢ª¥ cp866.',0
.3 db 'â¨ ᨬ¢®«ë ¡ã¤ãâ § ¬¥­¥­ë ­  ¯®¤çñન¢ ­¨ï.',0
aEnterPassword db '‚¢¥¤¨â¥ ¯ à®«ì:',0
aEnterPasswordLen = $ - aEnterPassword - 1
aEnterPasswordTitle db '‚¢®¤ ¯ à®«ï',0
aArchiveDataError db 'Žè¨¡ª  ¢ ¤ ­­ëå  à娢 ',0
aArchiveDataErrorPass db 'Žè¨¡ª  ¢ ¤ ­­ëå  à娢  ¨«¨ ­¥¢¥à­ë© ¯ à®«ì',0
aChangePass db '‚¢¥á⨠¯ à®«ì',0
aNameTooLong db '‘«¨èª®¬ ¤«¨­­®¥ ¨¬ï',0
else
aContinue db 'Continue',0
aCancel db 'Cancel',0
aHeaderError db 'Invalid archive header',0
aReadError db 'Read error',0
aNoFreeRam db 'There is not enough of free RAM',0
aEncodingProblem db 'Encoding problem',0
aEncodingProblem_str db 'The names of some files in the archive contain',0
.2 db 'characters which can not be represented in cp866.',0
.3 db 'Such characters will be replaced to underscores.',0
aEnterPassword db 'Enter password:',0
aEnterPasswordLen = $ - aEnterPassword - 1
aEnterPasswordTitle db 'Get password',0
aArchiveDataError db 'Error in archive data',0
aArchiveDataErrorPass db 'Error in archive data or incorrect password',0
aChangePass db 'Enter password',0
aNameTooLong db 'Name is too long',0
end if
 
; kfar_arc supports [hmm... will support...] many archive types.
; OpenFilePlugin looks for supported archive signature and gives control
; to concrete handler if found.
; Other functions just determine type of opened archive and jumps to corresponding handler.
type_mem_stream = 0 ; memory stream - for file handles (returned from 'open')
type_7z = 1
 
; archive functions (types start from type_7z)
align 4
ClosePluginTable:
dd close_7z
ReadFolderTable:
dd ReadFolder_7z
SetFolderTable:
dd SetFolder_7z
GetFilesTable:
dd GetFiles_7z
getattrTable:
dd getattr_7z
openTable:
dd open_file_7z
 
; file functions (types start from type_mem_stream)
readTable:
dd read_mem_stream
dd read_7z
setposTable:
dd setpos_mem_stream
dd setpos_7z
closeTable:
dd close_mem_stream
dd close_file_7z
 
; pointers for SayErr and Message
ContinueBtn dd aContinue
HeaderError_ptr dd aHeaderError
aReadError_ptr dd aReadError
aNoFreeRam_ptr dd aNoFreeRam
aEncodingProblem_str_ptr:
dd aEncodingProblem_str
dd aEncodingProblem_str.2
dd aEncodingProblem_str.3
aNameTooLong_ptr dd aNameTooLong
aArchiveDataError_ptr dd aArchiveDataError
aArchiveDataErrorPass_ptr dd aArchiveDataErrorPass
CancelPassBtn dd aCancel
dd aChangePass
 
; "enter password" dialog for KFar
password_dlg:
dd 1 ; use standard dialog colors
dd -1 ; center window by x
dd -1 ; center window by y
.width dd ? ; width (will be filled according to current console width)
dd 2 ; height
dd 4, 2 ; border size
dd aEnterPasswordTitle ; title
dd ? ; colors (will be set by KFar)
dd 0, 0 ; reserved for DlgProc
dd 2 ; 2 controls
; the string "enter password"
dd 1 ; type: static
dd 1,0 ; upper-left position
.width1 dd ?,0 ; bottom-right position
dd aEnterPassword ; data
dd 0 ; flags
; editbox for password
dd 3 ; type: edit
dd 1,1 ; upper-left position
.width2 dd ?,0 ; bottom-right position
dd password_data ; data
dd 2Ch ; flags
 
IncludeIGlobals
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; Uninitialized data ;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
section '.udata' data readable writable align 16
kfar_info dd ?
crc_table rd 256
_esp dd ?
_ebp dd ?
bufsize dd ?
bufptr dd ?
bufend dd ?
buffer rb 1024
inStream dd ?
hOut dd ?
.allocated dd ?
 
error_proc dd ?
clear_proc dd ?
 
; import from kfar
read dd ?
seek dd ?
close dd ?
pgalloc dd ?
pgrealloc dd ?
pgfree dd ?
getfreemem dd ?
DialogBox dd ?
SayErr dd ?
Message dd ?
cur_console_size dd ?
 
; data for editbox in kfar dialog
password_maxlen = 512
password_data:
.maxlen dd ?
.pos dd ?
.start dd ?
password_ansi rb password_maxlen+1
bPasswordDefined db ?
 
; converted password
password_unicode rw password_maxlen+1
password_size dd ?
 
IncludeUGlobals
 
bWasWarning db ?
/programs/fs/kfar/trunk/kfar_arc/kglobals.inc
0,0 → 1,50
;------------------------------------------------------------------
; use "iglobal" for inserting initialized global data definitions.
;------------------------------------------------------------------
macro iglobal {
IGlobals equ IGlobals,
macro __IGlobalBlock { }
 
;-------------------------------------------------------------
; use 'uglobal' for inserting uninitialized global definitions.
; even when you define some data values, these variables
; will be stored as uninitialized data.
;-------------------------------------------------------------
macro uglobal {
UGlobals equ UGlobals,
macro __UGlobalBlock { }
 
endg fix } ; Use endg for ending iglobal and uglobal blocks.
 
macro IncludeIGlobals{
macro IGlobals dummy,[n] \{ __IGlobalBlock
purge __IGlobalBlock \}
match I, IGlobals \{ I \} }
 
 
macro IncludeUGlobals{
macro UGlobals dummy,[n] \{
\common
\local begin, size
begin = $
virtual at $
\forward
__UGlobalBlock
purge __UGlobalBlock
\common
size = $ - begin
end virtual
rb size
\}
match U, UGlobals \{ U \} }
 
macro IncludeAllGlobals {
IncludeIGlobals
IncludeUGlobals
}
iglobal
endg
 
uglobal
endg
/programs/fs/kfar/trunk/kfar_arc/lang.inc
0,0 → 1,0
lang fix ru
/programs/fs/kfar/trunk/kfar_arc/lzma.inc
0,0 → 1,581
; LZMA decoder for *.7z archives.
; Based on C decoder in LZMA SDK (c) Igor Pavlov.
; Portions by Diamond, 2006, 2007.
lzma_decoder:
virtual at 0
.outStream rb streamInfo.size
.inStream dd ?
 
; RangeDecoder data
.inLen dd ?
.inPtr dd ?
.code dd ?
.range dd ?
 
; parameters
.pb db ? ; pos state bits (0 - 4)
.lp db ? ; literal pos state bits (0 - 4)
.lc db ? ; literal context bits (0 - 8)
.previousByte db ?
.posStateMask dd ? ; (1 shl .pb)-1
.literalPosMask dd ? ; (1 shl .lp)-1
 
; constants
.kNumPosBitsMax = 4
.kNumPosStatesMax = (1 shl .kNumPosBitsMax)
 
.kLenNumLowBits = 3
.kLenNumLowSymbols = (1 shl .kLenNumLowBits)
.kLenNumMidBits = 3
.kLenNumMidSymbols = (1 shl .kLenNumMidBits)
.kLenNumHighBits = 8
.kLenNumHighSymbols = (1 shl .kLenNumHighBits)
 
.LenChoice = 0
.LenChoice2 = 1
.LenLow = 2
.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols)
 
.kNumStates = 12
.kNumLitStates = 7
.kStartPosModelIndex = 4
.kEndPosModelIndex = 14
.kNumFullDistances = (1 shl (.kEndPosModelIndex/2))
.kNumPosSlotBits = 6
.kNumLenToPosStates = 4
.kNumAlignBits = 4
.kAlignTableSize = (1 shl .kNumAlignBits)
.kMatchMinLen = 2
 
.IsMatch = 0
.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax))
.IsRepG0 = (.IsRep + .kNumStates)
.IsRepG1 = (.IsRepG0 + .kNumStates)
.IsRepG2 = (.IsRepG1 + .kNumStates)
.IsRep0Long = (.IsRepG2 + .kNumStates)
.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
.Lencoder = (.Align_ + .kAlignTableSize)
.RepLencoder = (.Lencoder + .kNumLenProbs)
.Literal = (.RepLencoder + .kNumLenProbs)
 
LZMA_BASE_SIZE = 1846 ; must be ==Literal
LZMA_LIT_SIZE = 768
 
.kNumTopBits = 24
.kTopValue = (1 shl .kNumTopBits)
 
.kNumBitModelTotalBits = 11
.kBitModelTotal = (1 shl .kNumBitModelTotalBits)
.kNumMoveBits = 5
 
; variables
.continue dd ?
.ecx dd ?
.outEnd dd ?
.dictSize dd ?
.state dd ?
.rep0 dd ?
.rep1 dd ?
.rep2 dd ?
.rep3 dd ?
.p rd LZMA_BASE_SIZE
.basesize = $
; rd LZMA_LIT_SIZE shl (.lc+.lp)
end virtual
 
.fillBuf:
mov ebp, eax
mov ebx, [ebp+.state]
jecxz .nodata
add ecx, edi
mov [ebp+.outEnd], ecx
mov esi, [ebp+.inPtr]
jmp [ebp+.continue]
.nodata:
popad
ret
.start:
mov eax, [ebp+.inStream]
call fillBuf
mov esi, [eax+streamInfo.bufPtr]
mov eax, [eax+streamInfo.bufDataLen]
sub eax, 5
jb return.err
mov [ebp+.inLen], eax
inc esi
lodsd
bswap eax
mov [ebp+.code], eax
or [ebp+.range], -1
.main_loop:
cmp edi, [ebp+.outEnd]
jae .main_loop_done
mov edx, edi
and edx, [ebp+.posStateMask]
mov eax, ebx
shl eax, .kNumPosBitsMax
add eax, edx
lea eax, [ebp + .p + .IsMatch*4 + eax*4]
call .RangeDecoderBitDecode
jc .1
movzx eax, [ebp+.previousByte]
mov ah, dl
and ah, byte [ebp+.literalPosMask]
mov cl, 8
sub cl, [ebp+.lc]
shr eax, cl
imul eax, LZMA_LIT_SIZE*4
lea eax, [ebp + eax + .p+.Literal*4]
cmp ebx, .kNumLitStates
jb .literal
xor edx, edx
sub edx, [ebp+.rep0]
mov dl, [edi + edx]
call .LzmaLiteralDecodeMatch
jmp @f
.literal:
call .LzmaLiteralDecode
@@:
mov [ebp+.previousByte], al
stosb
mov al, bl
cmp bl, 4
jb @f
mov al, 3
cmp bl, 10
jb @f
mov al, 6
@@: sub bl, al
jmp .main_loop
.1:
lea eax, [ebp + .p + .IsRep*4 + ebx*4]
call .RangeDecoderBitDecode
jnc .10
lea eax, [ebp + .p + .IsRepG0*4 + ebx*4]
call .RangeDecoderBitDecode
jc .111
mov eax, ebx
shl eax, .kNumPosBitsMax
add eax, edx
lea eax, [ebp + .p + .IsRep0Long*4 + eax*4]
call .RangeDecoderBitDecode
jc .1101
cmp bl, 7
setae bl
lea ebx, [9 + ebx + ebx]
xor edx, edx
sub edx, [ebp+.rep0]
mov al, [edi + edx]
stosb
mov [ebp+.previousByte], al
jmp .main_loop
.111:
lea eax, [ebp + .p + .IsRepG1*4 + ebx*4]
call .RangeDecoderBitDecode
mov eax, [ebp+.rep1]
jnc .l3
.l1:
lea eax, [ebp + .p + .IsRepG2*4 + ebx*4]
call .RangeDecoderBitDecode
mov eax, [ebp+.rep2]
jnc .l2
xchg [ebp+.rep3], eax
.l2:
push [ebp+.rep1]
pop [ebp+.rep2]
.l3:
xchg eax, [ebp+.rep0]
mov [ebp+.rep1], eax
.1101:
lea eax, [ebp + .p + .RepLencoder*4]
call .LzmaLenDecode
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 8
jmp .repmovsb
.10:
mov eax, [ebp+.rep0]
xchg eax, [ebp+.rep1]
xchg eax, [ebp+.rep2]
xchg eax, [ebp+.rep3]
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 7
lea eax, [ebp + .p + .Lencoder*4]
call .LzmaLenDecode
mov eax, .kNumLenToPosStates-1
cmp eax, ecx
jb @f
mov eax, ecx
@@:
push ecx
mov ecx, .kNumPosSlotBits
shl eax, cl
lea eax, [ebp + .p+.PosSlot*4 + eax*4]
call .RangeDecoderBitTreeDecode
mov [ebp+.rep0], ecx
cmp ecx, .kStartPosModelIndex
jb .l6
push ecx
mov eax, ecx
and eax, 1
shr ecx, 1
or eax, 2
dec ecx
shl eax, cl
mov [ebp+.rep0], eax
pop edx
cmp edx, .kEndPosModelIndex
jae .l5
sub eax, edx
lea eax, [ebp + .p + (.SpecPos - 1)*4 + eax*4]
call .RangeDecoderReverseBitTreeDecode
add [ebp+.rep0], ecx
jmp .l6
.l5:
sub ecx, .kNumAlignBits
call .RangeDecoderDecodeDirectBits
mov ecx, .kNumAlignBits
shl eax, cl
add [ebp+.rep0], eax
lea eax, [ebp+.p+.Align_*4]
call .RangeDecoderReverseBitTreeDecode
add [ebp+.rep0], ecx
.l6:
pop ecx
inc [ebp+.rep0]
jz .main_loop_done
.repmovsb:
add ecx, .kMatchMinLen
.repmovsbz:
push esi
.repmovsbr:
mov eax, [ebp+.rep0]
cmp eax, [ebp+.dictSize]
jae return.err
mov esi, edi
sub esi, eax
mov eax, [ebp+streamInfo.bufPtr]
sub eax, esi
ja .repmovsb0
mov eax, [ebp+.outEnd]
sub eax, edi
push ecx
cmp ecx, eax
jb @f
mov ecx, eax
@@:
sub [esp], ecx
rep movsb
pop ecx
jz .repmovsb1
pop [ebp+.inPtr]
mov [ebp+.state], ebx
mov [ebp+.ecx], ecx
mov [ebp+.continue], .restart_repmovsb
popad
ret
.repmovsb0:
mov edx, [ebp+.dictSize]
cmp edx, [ebp+streamInfo.bufSize]
jnz return.err
add esi, edx
push ecx
cmp ecx, eax
jb @f
mov ecx, eax
@@:
mov eax, [ebp+.outEnd]
sub eax, edi
cmp ecx, eax
jb @f
mov ecx, eax
@@:
sub [esp], ecx
rep movsb
pop ecx
jnz .repmovsbr
.repmovsb1:
pop esi
mov al, [edi-1]
mov [ebp+.previousByte], al
jmp .main_loop
.main_loop_done:
mov [ebp+.state], ebx
mov [ebp+.continue], .main_loop
mov [ebp+.inPtr], esi
popad
ret
.restart_repmovsb:
mov ecx, [ebp+.ecx]
jmp .repmovsbz
 
.RangeDecoderBitDecode:
; in: eax->prob
; out: CF=bit; destroys eax
push edx
mov edx, [ebp+.range]
shr edx, .kNumBitModelTotalBits
imul edx, [eax]
cmp [ebp+.code], edx
jae .ae
mov [ebp+.range], edx
mov edx, .kBitModelTotal
sub edx, [eax]
shr edx, .kNumMoveBits
add [eax], edx
clc
.n:
lahf
cmp [ebp+.range], .kTopValue
jae @f
shl [ebp+.range], 8
shl [ebp+.code], 8
sub [ebp+.inLen], 1
js .refill1
.refilled1:
lodsb
mov byte [ebp+.code], al
@@:
sahf
pop edx
ret
.ae:
sub [ebp+.range], edx
sub [ebp+.code], edx
mov edx, [eax]
shr edx, .kNumMoveBits
sub [eax], edx
stc
jmp .n
 
.refill1:
push eax
call .refill
pop eax
jmp .refilled1
 
.refill:
mov eax, [ebp+.inStream]
cmp dword [eax+streamInfo.fullSize+4], 0
jnz @f
cmp dword [eax+streamInfo.fullSize], 0
jz return.err
@@:
call fillBuf
mov esi, [eax+streamInfo.bufPtr]
mov eax, [eax+streamInfo.bufDataLen]
dec eax
js return.err
mov [ebp+.inLen], eax
ret
 
.refill2:
call .refill
jmp .refilled2
 
.RangeDecoderDecodeDirectBits:
; in: ecx=numTotalBits
; out: eax=result; destroys edx
xor eax, eax
.l:
shr [ebp+.range], 1
shl eax, 1
mov edx, [ebp+.code]
sub edx, [ebp+.range]
jb @f
mov [ebp+.code], edx
or eax, 1
@@:
cmp [ebp+.range], .kTopValue
jae @f
shl [ebp+.range], 8
shl [ebp+.code], 8
push eax
dec [ebp+.inLen]
js .refill2
.refilled2:
lodsb
mov byte [ebp+.code], al
pop eax
@@:
loop .l
ret
 
.LzmaLiteralDecode:
; in: eax->probs
; out: al=byte; destroys edx
push ecx
mov ecx, 1
@@:
push eax
lea eax, [eax+ecx*4]
call .RangeDecoderBitDecode
pop eax
adc cl, cl
jnc @b
.LzmaLiteralDecode.ret:
mov al, cl
pop ecx
ret
.LzmaLiteralDecodeMatch:
; in: eax->probs, dl=matchByte
; out: al=byte; destroys edx
push ecx
mov ecx, 1
.LzmaLiteralDecodeMatch.1:
add dl, dl
setc ch
push eax
lea eax, [eax+ecx*4+0x100*4]
call .RangeDecoderBitDecode
pop eax
adc cl, cl
jc .LzmaLiteralDecode.ret
xor ch, cl
test ch, 1
mov ch, 0
jnz @b
jmp .LzmaLiteralDecodeMatch.1
 
.LzmaLenDecode:
; in: eax->prob, edx=posState
; out: ecx=len
push eax
add eax, .LenChoice*4
call .RangeDecoderBitDecode
pop eax
jnc .0
push eax
add eax, .LenChoice2*4
call .RangeDecoderBitDecode
pop eax
jc @f
mov ecx, .kLenNumMidBits
shl edx, cl
lea eax, [eax + .LenMid*4 + edx*4]
call .RangeDecoderBitTreeDecode
add ecx, .kLenNumLowSymbols
ret
@@:
add eax, .LenHigh*4
mov ecx, .kLenNumHighBits
call .RangeDecoderBitTreeDecode
add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
ret
.0:
mov ecx, .kLenNumLowBits
shl edx, cl
lea eax, [eax + .LenLow*4 + edx*4]
.RangeDecoderBitTreeDecode:
; in: eax->probs,ecx=numLevels
; out: ecx=length; destroys edx
push ebx
mov edx, 1
mov ebx, edx
@@:
push eax
lea eax, [eax+edx*4]
call .RangeDecoderBitDecode
pop eax
adc dl, dl
add bl, bl
loop @b
sub dl, bl
pop ebx
mov ecx, edx
ret
.RangeDecoderReverseBitTreeDecode:
; in: eax->probs,ecx=numLevels
; out: ecx=length; destroys edx
push ebx ecx
mov edx, 1
xor ebx, ebx
@@:
push eax
lea eax, [eax+edx*4]
call .RangeDecoderBitDecode
lahf
adc edx, edx
sahf
rcr ebx, 1
pop eax
loop @b
pop ecx
rol ebx, cl
mov ecx, ebx
pop ebx
ret
 
; LZMA parameters:
; db lc + 9 * (lp + 5 * pb)
; dd dictionarySize
 
lzma_get_buf_size:
cmp dword [esi-4], 5
jb return.err
push ecx
lodsb
aam 9
mov cl, al
mov al, ah
aam 5
add cl, al
mov eax, LZMA_LIT_SIZE
shl eax, cl
lea eax, [lzma_decoder.basesize+eax*4]
pop ecx
mov edx, [esi]
ret
 
lzma_init_decoder:
lodsb
aam 9
mov [ebp+lzma_decoder.lc], al
mov al, ah
aam 5
mov [ebp+lzma_decoder.lp], al
mov [ebp+lzma_decoder.pb], ah
cmp ah, lzma_decoder.kNumPosBitsMax
ja return.err
mov cl, ah
lodsd
mov [ebp+lzma_decoder.dictSize], eax
push 1
pop eax
shl eax, cl
dec eax
mov [ebp+lzma_decoder.posStateMask], eax
mov cl, [ebp+lzma_decoder.lp]
push 1
pop eax
shl eax, cl
dec eax
mov [ebp+lzma_decoder.literalPosMask], eax
mov [ebp+streamInfo.fillBuf], lzma_decoder.fillBuf
mov [ebp+lzma_decoder.continue], lzma_decoder.start
xor eax, eax
mov [ebp+lzma_decoder.previousByte], al
mov [ebp+lzma_decoder.state], eax
inc eax
lea edi, [ebp+lzma_decoder.rep0]
stosd
stosd
stosd
mov eax, LZMA_LIT_SIZE
mov cl, [ebp+lzma_decoder.lc]
add cl, [ebp+lzma_decoder.lp]
shl eax, cl
lea ecx, [eax+lzma_decoder.Literal]
mov eax, lzma_decoder.kBitModelTotal/2
lea edi, [ebp+lzma_decoder.p]
rep stosd
ret
/programs/fs/kfar/trunk/kfar_arc/ppmd.inc
0,0 → 1,1485
; PPMD decoder, ported from C++ sources of 7-Zip (c) Igor Pavlov
; C++ code is based on Dmitry Shkarin's PPMdH code
uglobal
ppmd_decoder.NS2Indx rb 256
ppmd_decoder.NS2BSIndx rb 256
ppmd_decoder.HB2Flag rb 256
ppmd_decoder.Indx2Units rb ppmd_decoder.N_INDEXES
ppmd_decoder.Units2Indx rb 128
endg
 
iglobal
label ppmd_decoder.InitBinEsc word
dw 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051
ppmd_decoder.ExpEscape db 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2
endg
 
init_ppmd:
; NS2Indx table
mov edi, ppmd_decoder.NS2Indx
xor eax, eax
stosb
inc eax
stosb
inc eax
stosb
mov edx, 3-256
@@:
lea ecx, [eax-1]
inc eax
add edx, ecx
jc @f
rep stosb
jmp @b
@@:
sub ecx, edx
rep stosb
; NS2BSIndx table
xor eax, eax
stosb
add al, 2
stosb
add al, 2
mov cl, 9
rep stosb
add al, 2
mov cl, 256-11
rep stosb
; HB2Flag table
mov cl, 0x40/4
xor eax, eax
rep stosd
mov al, 8
mov cl, 0x100-0x40
rep stosb
; Indx2Units table
mov eax, 0x04030201
stosd
mov eax, 0x0C0A0806
stosd
mov eax, 0x1815120F
stosd
mov al, 0x1C
@@:
stosb
add al, 4
cmp al, 0x80
jbe @b
; Units2Indx table
xor eax, eax
xor edx, edx
inc edx
xor ecx, ecx
@@:
cmp [ppmd_decoder.Indx2Units+eax], dl
adc al, 0
stosb
inc edx
cmp dl, 0x80
jbe @b
ret
 
ppmd_decoder:
virtual at 0
; base is standard structure
.outStream rb streamInfo.size
.inStream dd ?
 
; RangeDecoder data
.inLen dd ?
.inPtr dd ?
.code dd ?
.range dd ?
 
.outSize dd ? ; number of bytes rest for output
 
; PPMD data
.order db ?
.GlueCount db ?
.bInited db ?
rb 1
.usedMemorySize dd ?
 
; CSubAllocator constants
.N1 = 4
.N2 = 4
.N3 = 4
.N4 = (128+3-1*.N1-2*.N2-3*.N3)/4
.UNIT_SIZE = 12
.N_INDEXES = .N1+.N2+.N3+.N4
.kExtraSize = .UNIT_SIZE*3
.kMaxMemBlockSize = 0xFFFFFFFF - .kExtraSize
 
; CSubAllocator data
.HeapStart dd ?
.LoUnit dd ?
.HiUnit dd ?
.pText dd ?
.UnitsStart dd ?
.FreeList rd .N_INDEXES
 
; Context constants
.INT_BITS = 7
.PERIOD_BITS = 7
.TOT_BITS = .INT_BITS + .PERIOD_BITS
.INTERVAL = 1 shl .INT_BITS
.BIN_SCALE = 1 shl .TOT_BITS
.MAX_FREQ = 124
 
.kMaxOrderCompress = 32
.MAX_O = 255
 
; CDecodeInfo (inherits from CInfo) data
; SEE2_CONTEXT is 4 bytes long
.SEE2Cont rd 25*16
.DummySEE2Cont dd ?
.MinContext dd ?
.MaxContext dd ?
.FoundState dd ? ; found next state transition
.NumMasked dd ?
.InitEsc dd ?
.OrderFall dd ?
.RunLength dd ?
.InitRL dd ?
.CharMask rb 256
.EscCount db ?
.PrintCount db ?
.PrevSuccess db ?
.HiBitsFlag db ?
.BinSumm rw 128*64
 
.basesize = $
.Base:
; rb .kExtraSize + [.usedMemorySize]
end virtual
 
.init:
mov eax, [eax+.inStream]
call fillBuf
mov esi, [eax+streamInfo.bufPtr]
mov eax, [eax+streamInfo.bufDataLen]
sub eax, 5
jb return.err
mov [ebp+.inLen], eax
inc esi
lodsd
mov [ebp+.inPtr], esi
bswap eax
mov [ebp+.code], eax
or [ebp+.range], -1
mov [ebp+.bInited], 1
call .StartModelRare
mov eax, ebp
jmp .mainloop
 
.fillBuf:
mov ebp, eax
mov [eax+.outSize], ecx
cmp [eax+.bInited], 0
jz .init
.mainloop:
sub [ebp+.outSize], 1
js .mainloopdone
; cmp edi, 0xde070+0x18
; jnz @f
; int3
;@@:
call .DecodeSymbol
jmp .mainloop
.mainloopdone:
popad
ret
 
.GetBinSumm:
; CInfo::GetBinSumm(ebx=rs, ecx=numStates)
movzx eax, [ebp+.PrevSuccess]
movzx edx, [.NS2BSIndx+ecx-1]
add eax, edx
mov edx, [ebp+.FoundState]
movzx edx, byte [edx]
movzx edx, [.HB2Flag+edx]
mov [ebp+.HiBitsFlag], dl
add eax, edx
movzx edx, byte [ebx]
movzx edx, [.HB2Flag+edx]
lea eax, [eax+edx*2]
mov edx, [ebp+.RunLength]
shr edx, 26
and edx, 0x20
add eax, edx
movzx edx, byte [ebx+1]
shl edx, 6
add eax, edx
lea ecx, [ebp+.BinSumm+eax*2-2*64]
ret
 
.StartModelRare:
; CInfo::StartModelRare(.order)
mov [ebp+.EscCount], 1
mov [ebp+.PrintCount], 1
; N.B.
; 1. Original code has some handling of [.order]<2, but this handling is incorrect
; and causes exception (access violation).
; 2. 7-Zip never generates archives with [.order]<2 due to input preprocessing
; (for PPMd method in switch -mo=<n> archiver checks that 2 <= n <= 32).
; 3. If manually created archive says [.order]<2, the exception will be generated
; in StartModelRare, but it will be handled in Code() resulting in "data error".
cmp [ebp+.order], 2
jb return.err
mov byte [ebp+.DummySEE2Cont+2], .PERIOD_BITS
 
.RestartModelRare:
; CInfo::RestartModelRare(void)
push edi
lea edi, [ebp+.CharMask]
xor eax, eax
push 0x40
pop ecx
rep stosd
; CSubAllocator::InitSubAllocator start
mov [ebp+.GlueCount], al
lea edi, [ebp+.FreeList]
mov cl, .N_INDEXES
rep stosd
mov ebx, [ebp+.HeapStart]
mov [ebp+.pText], ebx
add ebx, [ebp+.usedMemorySize]
mov [ebp+.HiUnit], ebx
mov eax, [ebp+.usedMemorySize]
xor edx, edx
mov cl, 8*.UNIT_SIZE
div ecx
imul eax, 7*.UNIT_SIZE
sub ebx, eax
mov [ebp+.LoUnit], ebx
mov [ebp+.UnitsStart], ebx
; CSubAllocator::InitSubAllocator end
pop edi
movzx eax, [ebp+.order]
cmp al, 12
jb @f
mov al, 12
@@:
neg eax
dec eax
mov [ebp+.InitRL], eax
mov [ebp+.RunLength], eax
call .AllocContext
mov [ebp+.MinContext], eax
mov [ebp+.MaxContext], eax
and dword [eax+8], 0
mov esi, eax
movzx edx, [ebp+.order]
mov [ebp+.OrderFall], edx
mov dword [eax], 257*10000h+256
mov ecx, 256/2
call .AllocUnits
mov [ebp+.FoundState], eax
mov [esi+4], eax
push edi
mov edi, eax
xor eax, eax
mov [ebp+.PrevSuccess], al
@@:
stosb
mov byte [edi], 1
and dword [edi+1], 0
add edi, 5
inc al
jnz @b
lea edi, [ebp+.BinSumm]
push 2
pop ecx
.rmr1:
mov esi, .InitBinEsc
@@:
lodsw
xor edx, edx
div ecx
sub eax, .BIN_SCALE
neg eax
mov [edi+2*8], ax
mov [edi+2*16], ax
mov [edi+2*24], ax
mov [edi+2*32], ax
mov [edi+2*40], ax
mov [edi+2*48], ax
mov [edi+2*56], ax
stosw
cmp esi, .InitBinEsc+2*8
jb @b
add edi, 128-16
inc ecx
cmp ecx, 128+2
jb .rmr1
lea edi, [ebp+.SEE2Cont]
mov eax, (10 shl (.PERIOD_BITS-4)) + ((.PERIOD_BITS-4) shl 16) + (4 shl 24)
push 25
pop edx
@@:
push 16
pop ecx
rep stosd
add ax, 5 shl (.PERIOD_BITS-4)
dec edx
jnz @b
pop edi
ret
 
.CreateSuccessors:
; CInfo::CreateSuccessors(bool al=skip,STATE* esi=p1)
push ebx edi
mov ebx, [ebp+.MinContext] ; ebx=pc
mov ecx, [ebp+.FoundState]
mov ecx, [ecx+2] ; ecx=UpBranch
sub esp, .MAX_O*4 ; esp=ps
mov edi, esp ; edi=pps
test al, al
jnz @f
mov eax, [ebp+.FoundState]
stosd
cmp dword [ebx+8], 0
jz .csnoloop
@@:
test esi, esi
jz .csloopstart
mov edx, esi ; edx=p
mov ebx, [ebx+8]
jmp .csloopentry
.csloopstart:
mov ebx, [ebx+8]
lea edx, [ebx+2]
cmp word [ebx], 1
jz .csloopentry
mov edx, [ebx+4]
mov eax, [ebp+.FoundState]
sub edx, 6
mov al, [eax]
@@:
add edx, 6
cmp al, [edx]
jnz @b
.csloopentry:
cmp ecx, [edx+2]
jz @f
mov ebx, [edx+2]
jmp .csnoloop
@@:
mov [edi], edx
add edi, 4
cmp dword [ebx+8], 0
jnz .csloopstart
.csnoloop:
cmp edi, esp
jz .csr
push eax
push eax
mov al, [ecx]
mov [esp], al
add ecx, 1
mov [esp+2], ecx
mov ah, [ebx+3]
cmp word [ebx], 1
jz .cs2
mov edx, [ebx+4]
sub edx, 6
@@:
add edx, 6
cmp [edx], al
jnz @b
movzx edx, byte [edx+1]
sub edx, 1 ; edx=cf
movzx ecx, word [ebx+2]
movzx eax, word [ebx]
sub ecx, eax
sub ecx, edx ; ecx=s0
lea eax, [edx+edx]
cmp eax, ecx
ja .cs0
lea eax, [edx*5]
cmp eax, ecx
seta ah
jmp .cs1
.cs0:
lea eax, [eax+ecx*2]
lea eax, [eax+ecx-1]
add ecx, ecx
xor edx, edx
div ecx
mov ah, al
.cs1:
add ah, 1
.cs2:
mov [esp+1], ah
sub edi, 8
.cs3:
; PPM_CONTEXT::createChild(this=ebx,pStats=[edi+4],FirstState=esp) begin
call .AllocContext
test eax, eax
jz .csr0
mov word [eax], 1
mov dx, [esp]
mov [eax+2], dx
mov edx, [esp+2]
mov [eax+4], edx
mov [eax+8], ebx
mov edx, [edi+4]
mov [edx+2], eax
; PPM_CONTEXT::createChild end
mov ebx, eax
sub edi, 4
cmp edi, esp
jnz .cs3
pop eax eax
.csr:
mov eax, ebx
@@:
add esp, .MAX_O*4
pop edi ebx
ret
.csr0:
pop eax eax
xor eax, eax
jmp @b
 
; CInfo::UpdateModel(void)
.UpdateModel:
mov ebx, [ebp+.FoundState]
xor esi, esi ; esi=p
movzx eax, word [ebx]
mov ebx, [ebx+2] ; ebx=fs.Successor
push eax
cmp ah, .MAX_FREQ/4
jae .um2
mov eax, [ebp+.MinContext]
mov eax, [eax+8]
test eax, eax
jz .um2
cmp word [eax], 1
jz .um1
push eax
mov esi, [eax+4]
mov al, [esp+4]
cmp al, [esi]
jz .um0
@@:
add esi, 6
cmp al, [esi]
jnz @b
mov al, [esi+1]
cmp al, [esi-6+1]
jb @f
mov eax, [esi]
xchg [esi-6], eax
mov [esi], eax
mov ax, [esi+4]
xchg [esi-6+4], ax
mov [esi+4], ax
sub esi, 6
@@:
.um0:
pop eax
cmp byte [esi+1], .MAX_FREQ-9
jae @f
add byte [esi+1], 2
add word [eax+2], 2
@@:
jmp .um2
.um1:
lea esi, [eax+2]
cmp byte [esi+1], 32
adc byte [esi+1], 0
.um2:
cmp [ebp+.OrderFall], 0
jnz .um3
pop eax
mov al, 1
call .CreateSuccessors
mov [ebp+.MinContext], eax
mov [ebp+.MaxContext], eax
mov edx, [ebp+.FoundState]
mov [edx+2], eax
test eax, eax
jz .RestartModel
ret
.um3:
mov edx, [ebp+.pText]
mov al, [esp]
mov [edx], al
add edx, 1 ; edx=Successor
mov [ebp+.pText], edx
cmp edx, [ebp+.UnitsStart]
jae .RestartModelPop
test ebx, ebx
jz .um4
cmp ebx, [ebp+.pText]
ja @f
push edx
xor eax, eax
call .CreateSuccessors
pop edx
mov ebx, eax
test eax, eax
jz .RestartModelPop
@@:
sub [ebp+.OrderFall], 1
jnz @f
mov edx, ebx
xor ecx, ecx
mov eax, [ebp+.MinContext]
cmp eax, [ebp+.MaxContext]
setnz cl
sub [ebp+.pText], ecx
@@:
jmp .um5
.um4:
mov eax, [ebp+.FoundState]
mov [eax+2], edx
mov ebx, [ebp+.MinContext]
.um5:
mov eax, [ebp+.MinContext]
movzx ecx, word [eax] ; ecx=ns
movzx eax, word [eax+2]
sub eax, ecx
push eax
movzx eax, byte [esp+5]
sub eax, 1
sub [esp], eax ; [esp]=s0
mov esi, [ebp+.MaxContext] ; ebx=pc
cmp esi, [ebp+.MinContext]
jz .um12
.um6:
movzx eax, word [esi]
cmp eax, 1
jz .um8
push eax
shr eax, 1
jc .um7
push esi
mov esi, [esi+4]
call .ExpandUnits
pop esi
mov [esi+4], eax
test eax, eax
jz .RestartModelPop3
.um7:
pop eax
add eax, eax
cmp eax, ecx
adc word [esi+2], 0
add eax, eax
cmp eax, ecx
ja @f
lea eax, [eax+eax+1]
cmp word [esi+2], ax
ja @f
add word [esi+2], 2
@@:
push edx
jmp .um9
.um8:
push edx ecx
mov ecx, 1
call .AllocUnits
pop ecx
test eax, eax
jz .RestartModelPop3
mov dx, [esi+2]
mov [eax], dx
mov edx, [esi+4]
mov [eax+2], edx
mov [esi+4], eax
movzx edx, byte [eax+1]
add edx, edx
cmp edx, (.MAX_FREQ/4-1)*2
jb @f
mov edx, .MAX_FREQ-4
@@:
mov [eax+1], dl
add edx, [ebp+.InitEsc]
cmp ecx, 4
sbb edx, -1
mov [esi+2], dx
.um9:
movzx edx, word [esi+2]
mov eax, [esp+4]
push ecx
lea ecx, [eax+edx] ; ecx=sf
add edx, 6
movzx eax, byte [esp+13]
add eax, eax
imul eax, edx ; eax=cf
lea edx, [ecx*3]
add edx, edx
cmp eax, edx
jae .um10
mov edx, 1
cmp ecx, eax
adc edx, 0
shl ecx, 2
add eax, 1
cmp ecx, eax
adc edx, 0
add word [esi+2], 3
jmp .um11
.um10:
lea ecx, [ecx*3]
lea edx, [ecx*3]
add eax, 1
push 4
cmp edx, eax
adc dword [esp], 0
add edx, ecx
cmp edx, eax
adc dword [esp], 0
add edx, ecx
cmp edx, eax
adc dword [esp], 0
pop edx
add [esi+2], dx
.um11:
movzx eax, word [esi]
lea eax, [eax*3]
add eax, eax
add eax, [esi+4]
mov ecx, [esp+4]
mov [eax+2], ecx
mov cl, [esp+12]
mov [eax], cl
mov [eax+1], dl
add word [esi], 1
pop ecx edx
mov esi, [esi+8]
cmp esi, [ebp+.MinContext]
jnz .um6
.um12:
pop eax
pop eax
mov [ebp+.MinContext], ebx
mov [ebp+.MaxContext], ebx
ret
.RestartModelPop3:
pop eax
pop eax
.RestartModelPop:
pop eax
.RestartModel:
call .RestartModelRare
mov [ebp+.EscCount], 0
mov [ebp+.PrintCount], 0xFF
ret
 
.rescale:
mov esi, [ebp+.MinContext]
movzx ecx, word [esi]
push ecx ; [esp]=OldNS
sub ecx, 1
mov ebx, [ebp+.FoundState]
cmp ebx, [esi+4]
jz .r1
.r0:
mov ax, [ebx]
xchg [ebx-6], ax
mov [ebx], ax
mov eax, [ebx+2]
xchg [ebx-6+2], eax
mov [ebx+2], eax
sub ebx, 6
cmp ebx, [esi+4]
jnz .r0
.r1:
add byte [ebx+1], 4
add word [esi+2], 4
movzx eax, byte [ebx+1]
movzx edx, word [esi+2]
sub edx, eax ; edx=EscFreq
cmp [ebp+.OrderFall], 1
sbb eax, -1
shr eax, 1
mov [ebx+1], al
mov [esi+2], ax
.r2:
add ebx, 6
movzx eax, byte [ebx+1]
sub edx, eax
cmp [ebp+.OrderFall], 1
sbb eax, -1
shr eax, 1
mov [ebx+1], al
add [esi+2], ax
cmp al, [ebx-6+1]
jbe .r3
push ecx
push ebx
push dword [ebx]
push word [ebx+4]
@@:
mov ecx, [ebx-6]
mov [ebx], ecx
mov cx, [ebx-6+4]
mov [ebx+4], cx
sub ebx, 6
cmp ebx, [esi+4]
jz @f
cmp al, [ebx-6+1]
ja @b
@@:
pop word [ebx+4]
pop dword [ebx]
pop ebx
pop ecx
.r3:
sub ecx, 1
jnz .r2
cmp byte [ebx+1], 0
jnz .r4
@@:
add ecx, 1
sub ebx, 6
cmp byte [ebx+1], 0
jz @b
add edx, ecx
sub word [esi], cx
cmp word [esi], 1
jnz .r4
pop ebx
mov eax, [esi+4]
movzx ecx, word [eax+4]
push ecx
push dword [eax]
movzx eax, byte [eax+1]
@@:
add eax, 1
shr eax, 1
shr edx, 1
cmp edx, 1
ja @b
mov [esp+1], al
add ebx, 1
shr ebx, 1
mov eax, [esi+4]
call .FreeUnits
lea ebx, [esi+2]
mov [ebp+.FoundState], ebx
pop dword [ebx]
pop eax
mov [ebx+4], ax
ret
.r4:
add edx, 1
shr edx, 1
add [esi+2], dx
pop ebx
add ebx, 1
shr ebx, 1
movzx ecx, word [esi]
add ecx, 1
shr ecx, 1
cmp ebx, ecx
jz @f
mov eax, [esi+4]
call .ShrinkUnits
mov [esi+4], eax
@@:
mov eax, [esi+4]
mov [ebp+.FoundState], eax
ret
 
.DecodeSymbol:
; CDecodeInfo::DecodeSymbol
mov esi, [ebp+.MinContext]
cmp word [esi], 1
jz .binsymbol
; CDecodeInfo::DecodeSymbol1 start
mov ebx, [esi+4] ; state
movzx ecx, word [esi+2]
mov eax, [ebp+.range]
xor edx, edx
div ecx
mov [ebp+.range], eax
mov ecx, eax
mov eax, [ebp+.code]
xor edx, edx
div ecx
movzx edx, byte [ebx+1]
cmp eax, edx
jae .ds0
push edx
add edx, edx
cmp dx, [esi+2]
pop edx
seta [ebp+.PrevSuccess]
movzx eax, [ebp+.PrevSuccess]
add [ebp+.RunLength], eax
xor eax, eax
call .RangeDecoder.Decode
mov [ebp+.FoundState], ebx
add edx, 4
mov [ebx+1], dl
add word [esi+2], 4
cmp edx, .MAX_FREQ
jbe @f
call .rescale
@@:
jmp .dscmn
.ds0:
mov [ebp+.PrevSuccess], 0
movzx ecx, word [esi]
sub ecx, 1
push eax
.ds1:
add ebx, 6
movzx eax, byte [ebx+1]
add edx, eax
cmp edx, [esp]
ja .ds2
sub ecx, 1
jnz .ds1
pop eax
mov eax, [ebp+.FoundState]
movzx eax, byte [eax]
mov al, [.HB2Flag+eax]
mov [ebp+.HiBitsFlag], al
mov eax, edx
movzx edx, word [esi+2]
sub edx, eax
call .RangeDecoder.Decode
mov al, [ebp+.EscCount]
movzx edx, byte [ebx]
mov [ebp+.CharMask+edx], al
movzx ecx, word [esi]
mov [ebp+.NumMasked], ecx
sub ecx, 1
@@:
sub ebx, 6
movzx edx, byte [ebx]
mov [ebp+.CharMask+edx], al
sub ecx, 1
jnz @b
mov [ebp+.FoundState], ecx
jmp .dscmn
.ds2:
pop eax
mov eax, edx
movzx edx, byte [ebx+1]
sub eax, edx
call .RangeDecoder.Decode
.update1:
mov [ebp+.FoundState], ebx
add byte [ebx+1], 4
add word [esi+2], 4
mov al, [ebx+1]
cmp al, [ebx-6+1]
jbe @f
mov eax, [ebx]
xchg eax, [ebx-6]
mov [ebx], eax
mov ax, [ebx+4]
xchg ax, [ebx-6+4]
mov [ebx+4], ax
sub ebx, 6
mov [ebp+.FoundState], ebx
cmp byte [ebx+1], .MAX_FREQ
jbe @f
call .rescale
@@:
jmp .dscmn
; CDecodeInfo::DecodeSymbol1 end
.binsymbol:
; CDecodeInfo::DecodeBinSymbol start
lea ebx, [esi+2]
mov ecx, [esi+8]
movzx ecx, word [ecx]
call .GetBinSumm
movzx eax, word [ecx]
call .RangeDecoder.DecodeBit
jc .ds3
mov [ebp+.FoundState], ebx
cmp byte [ebx+1], 128
adc byte [ebx+1], 0
movzx eax, word [ecx]
add eax, 1 shl (.PERIOD_BITS-2)
shr eax, .PERIOD_BITS
sub eax, .INTERVAL
sub [ecx], ax
mov [ebp+.PrevSuccess], 1
add [ebp+.RunLength], 1
jmp .dscmn
.ds3:
movzx eax, word [ecx]
add eax, 1 shl (.PERIOD_BITS-2)
shr eax, .PERIOD_BITS
sub [ecx], ax
movzx eax, word [ecx]
shr eax, 10
movzx eax, [.ExpEscape+eax]
mov [ebp+.InitEsc], eax
mov [ebp+.NumMasked], 1
mov al, [ebp+.EscCount]
movzx edx, byte [ebx]
mov [ebp+.CharMask+edx], al
mov [ebp+.PrevSuccess], 0
and [ebp+.FoundState], 0
; CDecodeInfo::DecodeBinSymbol end
.dscmn:
cmp [ebp+.FoundState], 0
jnz .dsfnd
.ds4:
add [ebp+.OrderFall], 1
mov eax, [ebp+.MinContext]
mov eax, [eax+8]
test eax, eax
jz return.err ; no end-of-stream mark
mov [ebp+.MinContext], eax
movzx ecx, word [eax]
sub ecx, [ebp+.NumMasked]
jz .ds4
; CDecodeInfo::DecodeSymbol2 start
call .makeEscFreq2
push eax
mov ebx, [esi+4]
sub ebx, 6
sub esp, 256*4
mov esi, esp
xor eax, eax
push eax
@@:
add ebx, 6
mov al, [ebx]
mov al, [ebp+.CharMask+eax]
cmp al, [ebp+.EscCount]
jz @b
mov al, [ebx+1]
add [esp], eax
mov [esi], ebx
add esi, 4
sub ecx, 1
jnz @b
add edx, [esp]
mov ecx, edx
mov eax, [ebp+.range]
xor edx, edx
div ecx
mov [ebp+.range], eax
mov eax, [ebp+.code]
xor edx, edx
div [ebp+.range]
cmp eax, [esp]
jae .ds5
pop ecx
mov esi, esp
xor ecx, ecx
@@:
mov ebx, [esi]
add esi, 4
movzx edx, byte [ebx+1]
add ecx, edx
cmp eax, ecx
jae @b
mov eax, ecx
movzx edx, byte [ebx+1]
sub eax, edx
call .RangeDecoder.Decode
add esp, 256*4
pop eax
mov cl, [eax+2]
cmp cl, .PERIOD_BITS
jae @f
sub byte [eax+3], 1
jnz @f
shl word [eax], 1
mov dl, 3
shl dl, cl
mov [eax+3], dl
add byte [eax+2], 1
@@:
.update2:
mov [ebp+.FoundState], ebx
add byte [ebx+1], 4
mov esi, [ebp+.MinContext]
add word [esi+2], 4
cmp byte [ebx+1], .MAX_FREQ
jbe @f
call .rescale
@@:
add [ebp+.EscCount], 1
mov eax, [ebp+.InitRL]
mov [ebp+.RunLength], eax
jmp .dsfnd
.ds5:
pop eax
mov edx, ecx
sub edx, eax
call .RangeDecoder.Decode
mov eax, [ebp+.MinContext]
movzx eax, word [eax]
mov ebx, eax
sub ebx, [ebp+.NumMasked]
mov [ebp+.NumMasked], eax
mov esi, esp
mov al, [ebp+.EscCount]
@@:
mov edx, [esi]
add esi, 4
movzx edx, byte [edx]
mov [ebp+.CharMask+edx], al
sub ebx, 1
jnz @b
add esp, 256*4
pop eax
add word [eax], cx
; CDecodeInfo::DecodeSymbol2 end
cmp [ebp+.FoundState], 0
jz .ds4
.dsfnd:
mov eax, [ebp+.FoundState]
mov al, [eax]
stosb
 
.NextContext:
; CInfo::NextContext(void)
mov ebx, [ebp+.FoundState]
mov ebx, [ebx+2]
cmp [ebp+.OrderFall], 0
jnz .nc0
cmp ebx, [ebp+.pText]
jbe .nc0
mov [ebp+.MinContext], ebx
mov [ebp+.MaxContext], ebx
ret
.nc0:
call .UpdateModel
cmp [ebp+.EscCount], 0
jz @f
ret
@@:
mov [ebp+.EscCount], 1
push edi
lea edi, [ebp+.CharMask]
mov ecx, 256/4
xor eax, eax
rep stosd
pop edi
ret
 
.makeEscFreq2:
; CInfo::makeEscFreq2(ecx=Diff)->{eax->SEE2_CONTEXT,edx=scale}
mov esi, [ebp+.MinContext]
cmp word [esi], 256
jz .mef0
movzx edx, [.NS2Indx+ecx-1]
shl edx, 4
mov eax, [esi+8]
movzx eax, word [eax]
sub ax, [esi]
cmp ecx, eax
adc edx, 0
movzx eax, word [esi]
push edx
lea edx, [eax*9]
lea edx, [edx+eax*2]
movzx eax, word [esi+2]
cmp eax, edx
pop edx
setc al
movzx eax, al
lea edx, [edx+eax*2]
cmp ecx, [ebp+.NumMasked]
setc al
lea edx, [edx+eax*4]
add dl, [ebp+.HiBitsFlag]
lea eax, [ebp+edx*4+.SEE2Cont]
movzx edx, word [eax]
push ecx
mov cl, [eax+2]
shr edx, cl
sub [eax], dx
pop ecx
cmp edx, 1
adc edx, 0
ret
.mef0:
lea eax, [ebp+.DummySEE2Cont]
mov edx, 1
ret
 
.RangeDecoder.DecodeBit:
; CRangeDecoder::DecodeBit(eax=size0,numTotalBits=.TOT_BITS)
mov edx, [ebp+.range]
shr edx, .TOT_BITS
imul eax, edx
cmp [ebp+.code], eax
jae .rddb
mov [ebp+.range], eax
call .RangeDecoder.Normalize
clc
ret
.rddb:
sub [ebp+.code], eax
sub [ebp+.range], eax
call .RangeDecoder.Normalize
stc
ret
 
.RangeDecoder.Decode:
imul eax, [ebp+.range]
sub [ebp+.code], eax
mov eax, [ebp+.range]
imul eax, edx
mov [ebp+.range], eax
.RangeDecoder.Normalize:
cmp byte [ebp+.range+3], 0
jz @f
ret
@@:
sub [ebp+.inLen], 1
js .refill
.filled:
shl [ebp+.range], 8
shl [ebp+.code], 8
mov eax, [ebp+.inPtr]
add [ebp+.inPtr], 1
mov al, [eax]
mov byte [ebp+.code], al
jmp .RangeDecoder.Normalize
.refill:
mov eax, [ebp+.inStream]
call fillBuf
push [eax+streamInfo.bufPtr]
pop [ebp+.inPtr]
mov eax, [eax+streamInfo.bufDataLen]
sub eax, 1
js return.err
mov [ebp+.inLen], eax
jmp .filled
 
.GlueFreeBlocks:
; CSubAllocator::GlueFreeBlocks, called from AllocUnitsRare
push eax
mov [ebp+.GlueCount], 255
mov edx, [ebp+.HeapStart]
add edx, [ebp+.usedMemorySize]
; we need add extra MEM_BLK with Stamp=0
and word [edx], 0
add edx, .UNIT_SIZE
mov eax, [ebp+.LoUnit]
cmp eax, [ebp+.HiUnit]
jz @f
mov byte [eax], 0
@@:
mov [edx+4], edx
mov [edx+8], edx
push ecx
xor ecx, ecx
.gfb1:
mov eax, [ebp+ecx*4+.FreeList]
test eax, eax
jz .gfb2
push dword [eax]
pop dword [ebp+ecx*4+.FreeList]
mov [eax+8], edx
push edx
mov edx, [edx+4]
mov [eax+4], edx
mov [edx+8], eax
or word [eax], 0xFFFF
movzx edx, [.Indx2Units+ecx]
mov [eax+2], dx
pop edx
mov [edx+4], eax
jmp .gfb1
.gfb2:
inc ecx
cmp ecx, .N_INDEXES
jb .gfb1
mov ecx, edx
.gfb3:
mov ecx, [ecx+4]
cmp ecx, edx
jz .gfb5
.gfb4:
movzx eax, word [ecx+2]
lea eax, [eax*3]
lea eax, [ecx+eax*4]
cmp word [eax], 0xFFFF
jnz .gfb3
push eax
mov ax, [eax+2]
add ax, [ecx+2]
pop eax
jc .gfb3
push edx
mov edx, [eax+4]
push dword [eax+8]
pop dword [edx+8]
mov edx, [eax+8]
push dword [eax+4]
pop dword [edx+4]
pop edx
mov ax, [eax+2]
add [ecx+2], ax
jmp .gfb4
.gfb5:
mov ecx, [edx+4]
cmp ecx, edx
jz .gfb8
mov eax, [ecx+4]
mov [eax+8], edx
mov [edx+4], eax
movzx eax, word [ecx+2]
push edx
.gfb6:
sub eax, 128
jbe .gfb7
mov edx, ecx
xchg edx, [ebp+.FreeList+(.N_INDEXES-1)*4]
mov [ecx], edx
add ecx, 128*.UNIT_SIZE
jmp .gfb6
.gfb7:
add eax, 128
movzx edx, [.Units2Indx+eax-1]
cmp [.Indx2Units+edx], al
jz @f
dec edx
push edx
movzx edx, [.Indx2Units+edx]
sub eax, edx
lea eax, [ebp+.FreeList+(eax-1)*4]
lea edx, [edx*3]
lea edx, [ecx+edx*4]
push dword [eax]
pop dword [edx]
mov [eax], edx
pop edx
@@:
mov eax, ecx
xchg eax, [ebp+.FreeList+edx*4]
mov [ecx], eax
pop edx
jmp .gfb5
.gfb8:
pop ecx
pop eax
mov edx, [ebp+.FreeList+eax*4]
test edx, edx
jz .aur.cont
push edx
mov edx, [edx]
mov [ebp+.FreeList+eax*4], edx
pop eax
ret
 
.AllocContext:
; CSubAllocator::AllocContext
mov eax, [ebp+.HiUnit]
cmp eax, [ebp+.LoUnit]
jz @f
sub eax, .UNIT_SIZE
mov [ebp+.HiUnit], eax
ret
@@:
mov eax, [ebp+.FreeList]
test eax, eax
jz @f
mov edx, [eax]
mov [ebp+.FreeList], edx
ret
@@:
xor eax, eax
jmp .AllocUnitsRare
 
.AllocUnits:
; CSubAllocator::AllocUnits(ecx)
movzx ecx, [.Units2Indx+ecx-1]
mov eax, [ebp+.FreeList+ecx*4]
test eax, eax
jz @f
mov edx, [eax]
mov [ebp+.FreeList+ecx*4], edx
ret
@@:
mov eax, [ebp+.LoUnit]
movzx edx, [.Indx2Units+ecx]
lea edx, [edx*3]
lea eax, [eax+edx*4]
cmp eax, [ebp+.HiUnit]
ja @f
xchg eax, [ebp+.LoUnit]
ret
@@:
mov eax, ecx
 
.AllocUnitsRare:
; CSubAllocator::AllocUnitsRare(eax)
cmp [ebp+.GlueCount], 0
jz .GlueFreeBlocks
.aur.cont:
push eax
.aur1:
inc eax
cmp eax, .N_INDEXES
jz .aur3
mov edx, [ebp+.FreeList+eax*4]
test edx, edx
jz .aur1
push edx
mov edx, [edx]
mov [ebp+.FreeList+eax*4], edx
call .SplitBlock
pop eax
pop edx
ret
.aur3:
dec [ebp+.GlueCount]
pop eax
movzx eax, [.Indx2Units+eax]
lea edx, [eax*3]
shl edx, 2
mov eax, [ebp+.UnitsStart]
sub eax, [ebp+.pText]
cmp eax, edx
jbe .aur4
mov eax, [ebp+.UnitsStart]
sub eax, edx
mov [ebp+.UnitsStart], eax
ret
.aur4:
xor eax, eax
ret
 
.SplitBlock:
; CSubAllocator::SplitBlock(pv=[esp+4],oldIndx=eax,newIndx=[esp+8])
push eax
mov edx, [esp+12]
movzx eax, [.Indx2Units+eax]
movzx edx, [.Indx2Units+edx]
sub eax, edx
lea edx, [edx*3]
push ecx
mov ecx, [esp+12]
lea ecx, [ecx+edx*4]
movzx edx, [.Units2Indx+eax-1]
cmp [.Indx2Units+edx], al
jz .aur2
push dword [ebp+.FreeList+(edx-1)*4]
pop dword [ecx]
mov [ebp+.FreeList+(edx-1)*4], ecx
movzx edx, [.Indx2Units+edx-1]
sub eax, edx
lea edx, [edx*3]
lea ecx, [ecx+edx*4]
.aur2:
movzx eax, [.Units2Indx+eax-1]
push dword [ebp+.FreeList+eax*4]
pop dword [ecx]
mov [ebp+.FreeList+eax*4], ecx
pop ecx
pop eax
ret
 
.ExpandUnits:
; CSubAllocator::ExpandUnits(void* oldPtr=esi, int oldNU=eax)
push edx
movzx edx, [.Units2Indx + eax - 1]
cmp dl, [.Units2Indx + eax]
jnz @f
pop edx
mov eax, esi
ret
@@:
push eax ecx edx
lea ecx, [eax+1]
call .AllocUnits
pop edx
test eax, eax
jz @f
push esi edi
mov edi, eax
mov ecx, [esp+8+4]
lea ecx, [ecx*3]
rep movsd
pop edi esi
mov ecx, [ebp+.FreeList+edx*4]
mov [esi], ecx
mov [ebp+.FreeList+edx*4], esi
@@:
pop ecx
add esp, 4
pop edx
ret
 
.ShrinkUnits:
; CSubAllocator::ShrinkUnits(void* oldPtr=eax, int oldNU=ebx, int newNU=ecx)
push ecx
movzx ebx, [.Units2Indx+ebx-1]
movzx ecx, [.Units2Indx+ecx-1]
cmp ebx, ecx
jnz @f
pop ecx
ret
@@:
mov edx, [ebp+.FreeList+ecx*4]
test edx, edx
jz @f
push dword [edx]
pop [ebp+.FreeList+ecx*4]
pop ecx
push esi edi
mov esi, eax
mov edi, edx
lea ecx, [ecx*3]
rep movsd
pop edi esi
mov ecx, [ebp+.FreeList+ebx*4]
mov [eax], ecx
mov [ebp+.FreeList+ebx*4], eax
mov eax, edx
ret
@@:
push ecx
push eax
mov eax, ebx
call .SplitBlock
pop eax
pop ecx
pop ecx
ret
 
.FreeUnits:
; CSubAllocator::FreeUnits(void* ptr=eax, int oldNU=ebx)
movzx ebx, [.Units2Indx+ebx-1]
push [ebp+.FreeList+ebx*4]
pop dword [eax]
mov [ebp+.FreeList+ebx*4], eax
ret
 
ppmd_get_buf_size:
cmp dword [esi-4], 5
jb return.err
lodsb
lodsd
cmp eax, ppmd_decoder.kMaxMemBlockSize
ja return.err
add eax, ppmd_decoder.basesize + ppmd_decoder.kExtraSize
mov edx, 0x4000
ret
 
ppmd_init_decoder:
mov [ebp+ppmd_decoder.bInited], 0
; CDecoder::SetDecoderProperties2
lodsb
mov [ebp+ppmd_decoder.order], al
lodsd
mov [ebp+ppmd_decoder.usedMemorySize], eax
; CSubAllocator::CSubAllocator
xor eax, eax
mov [ebp+ppmd_decoder.GlueCount], al
lea edi, [ebp+ppmd_decoder.LoUnit]
mov ecx, (ppmd_decoder.SEE2Cont - ppmd_decoder.LoUnit)/4
rep stosd
; CSubAllocator::StartSubAllocator
lea eax, [ebp+ppmd_decoder.Base+ppmd_decoder.UNIT_SIZE]
mov [ebp+ppmd_decoder.HeapStart], eax
mov [ebp+streamInfo.fillBuf], ppmd_decoder.fillBuf
ret
/programs/fs/kfar/trunk/kfar_arc/sha256.inc
0,0 → 1,238
; Implementation of SHA-256 hash algorithm.
; Written by diamond in 2007.
 
iglobal
align 4
sha256_start_digest:
dd 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A
dd 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
sha256_const:
dd 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5
dd 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5
dd 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3
dd 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174
dd 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC
dd 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA
dd 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7
dd 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967
dd 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13
dd 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85
dd 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3
dd 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070
dd 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5
dd 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3
dd 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208
dd 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
endg
 
uglobal
align 4
sha256_buf rb 64
sha256_digest rd 8
sha256_count dd ?
sha256_size dq ?
endg
 
sha256_init:
mov edi, sha256_digest
mov esi, sha256_start_digest
push 8
pop ecx
rep movsd
xor eax, eax
stosd ; 0 bytes in buffer
stosd
stosd ; 0 bytes processed
ret
 
; Core of SHA-256: transform 64-byte 'sha256_buf' to updated 'sha256_digest'
sha256_transform:
mov esi, sha256_buf
mov edi, esi
rept 16
{
lodsd
bswap eax
stosd
}
push ebp
mov ebp, [esi+7*4]
mov edi, [esi+6*4]
push dword [esi+5*4]
push dword [esi+4*4]
push dword [esi+3*4]
push dword [esi+2*4]
push dword [esi+1*4]
push dword [esi+0*4]
xor ecx, ecx
.loop:
macro cmd1 cmd,a,b
{
if (b and 7) = 7
cmd a, ebp
else if (b and 7) = 6
cmd a, edi
else
cmd a, [esp+(b and 7)*4]
end if
}
macro cmd2 cmd,a,b
{
if (a and 7) = 7
cmd ebp, b
else if (a and 7) = 6
cmd edi, b
else
cmd [esp+(a and 7)*4], b
end if
}
rept 16 counter
{
cmd1 mov, eax, (5-counter)
ror eax, 6
mov edx, eax
ror eax, 5
xor edx, eax
ror eax, 14
xor edx, eax
cmd1 mov, eax, (6-counter)
cmd1 mov, esi, (7-counter)
xor eax, esi
cmd1 and, eax, (5-counter)
xor eax, esi
add edx, eax
add edx, [sha256_const+ecx+(counter-1)*4]
add edx, dword [sha256_buf+(counter-1)*4]
test ecx, ecx
jz @f
mov eax, dword [sha256_buf+((counter-3) and 15)*4]
mov esi, eax
ror eax, 17
shr esi, 10
xor esi, eax
ror eax, 2
xor esi, eax
add esi, dword [sha256_buf+((counter-8) and 15)*4]
mov eax, dword [sha256_buf+(counter and 15)*4]
mov ebx, eax
ror eax, 7
shr ebx, 3
xor ebx, eax
ror eax, 11
xor ebx, eax
add esi, ebx
add dword [sha256_buf+(counter-1)*4], esi
add edx, esi
@@:
cmd1 add, edx, (8-counter)
cmd2 mov, (8-counter), edx
cmd2 add, (4-counter), edx
cmd1 mov, ebx, (1-counter)
mov eax, ebx
cmd1 mov, edx, (2-counter)
mov esi, ebx
ror eax, 2
or esi, edx
and ebx, edx
cmd1 and, esi, (3-counter)
mov edx, eax
or esi, ebx
ror eax, 11
xor edx, eax
ror eax, 9
xor edx, eax
add esi, edx
cmd2 add, (8-counter), esi
}
purge cmd1,cmd2
add cl, 64
jnz .loop
mov esi, sha256_digest
pop eax
add [esi+0*4], eax
pop eax
add [esi+1*4], eax
pop eax
add [esi+2*4], eax
pop eax
add [esi+3*4], eax
pop eax
add [esi+4*4], eax
pop eax
add [esi+5*4], eax
add [esi+6*4], edi
add [esi+7*4], ebp
pop ebp
ret
 
sha256_update.transform:
push esi edx
call sha256_transform
pop edx esi
mov [sha256_count], ecx
 
sha256_update:
; in: esi->data, edx=size
mov eax, 64
sub eax, [sha256_count]
sub eax, edx
sbb ecx, ecx
and ecx, eax
add ecx, edx
sub edx, ecx
mov edi, sha256_buf
add edi, [sha256_count]
add [sha256_count], ecx
add dword [sha256_size], ecx
adc dword [sha256_size+4], 0
rep movsb
cmp edi, sha256_buf+64
jz .transform
.ret:
ret
 
sha256_final:
; out: edi->digest
push edi
mov eax, [sha256_count]
mov [sha256_buf+eax], 0x80
inc eax
cmp al, 64-8
jbe @f
lea edi, [sha256_buf+eax]
push 64
pop ecx
sub ecx, eax
xor eax, eax
rep stosb
push edx
call sha256_transform
pop edx
xor eax, eax
@@:
push 64-8
pop ecx
sub ecx, eax
lea edi, [sha256_buf+eax]
xor eax, eax
rep stosb
mov eax, dword [sha256_size]
mov edx, dword [sha256_size+4]
shld edx, eax, 3
shl eax, 3
bswap edx
bswap eax
xchg eax, edx
stosd
xchg eax, edx
stosd
call sha256_transform
mov esi, sha256_digest
mov cl, 8
pop edi
@@:
lodsd
bswap eax
stosd
loop @b
ret
/programs/fs/kfar/trunk/tools.inc
1,3 → 1,12
CHECK_FOR_LEAKS = 0
if CHECK_FOR_LEAKS
uglobal
allocatedregions rd 1024
endg
iglobal
numallocatedregions dd 0
endg
end if
pgalloc:
; in: ecx=size
; out: eax=pointer or NULL
7,6 → 16,20
push 12
pop ebx
int 0x40
if CHECK_FOR_LEAKS
test eax, eax
jz .no
.b:
mov ebx, [numallocatedregions]
cmp ebx, 1024
jb @f
int3
jmp $
@@:
mov [allocatedregions+ebx*4], eax
inc [numallocatedregions]
.no:
end if
pop ebx
ret
 
13,6 → 36,30
pgfree:
; in: ecx=pointer
; destroys eax
if CHECK_FOR_LEAKS
jecxz .no
mov eax, [numallocatedregions]
@@:
dec eax
js .a
cmp [allocatedregions+eax*4], ecx
jnz @b
jmp @f
.a:
int3
jmp $
@@:
dec [numallocatedregions]
@@:
cmp eax, [numallocatedregions]
jae @f
push [allocatedregions+eax*4+4]
pop [allocatedregions+eax*4]
inc eax
jmp @b
@@:
.no:
end if
push ebx
push 68
pop eax
31,6 → 78,29
push 20
pop ebx
int 0x40
if CHECK_FOR_LEAKS
test edx, edx
jz pgalloc.b
test eax, eax
jz .no
cmp eax, edx
jz .no
xor ebx, ebx
@@:
cmp ebx, [numallocatedregions]
jae .a
cmp [allocatedregions+ebx*4], edx
jz @f
inc ebx
jmp @b
@@:
mov [allocatedregions+ebx*4], eax
jmp .no
.a:
int3
jmp $
.no:
end if
pop ebx
ret
 
52,6 → 122,17
call pgrealloc
jmp xpgalloc.common
 
getfreemem:
; out: eax=size of free RAM in Kb
push ebx
push 18
pop eax
push 16
pop ebx
int 0x40
pop ebx
ret
 
get_error_msg:
; in: eax=error code
; out: eax=pointer to message (in static buffer)
85,6 → 166,7
test al, al
jnz @b
pop eax
dec edi
push edx ecx
test eax, eax
jns @f
162,7 → 244,8
pop eax
pop esi
jz .do
push eax
.big:
push esi
mov edi, aFileNameTooBig
.sayerr:
push dword aCannotLoadDLL
173,9 → 256,6
push 1
push eax
push 3
push -1
push -1
push dword aError
call SayErr
add esp, 16
xor eax, eax
192,9 → 272,15
mov edi, aInvalidDLL
test eax, eax
jz .sayerr
mov edx, eax
cmp ebp, -1
jnz @f
pop eax
xor eax, eax
ret
@@:
; initialize import
mov edi, aMissingExport
mov edx, eax
.import_loop:
lodsd
test eax, eax
/programs/fs/kfar/trunk/viewer.inc
6,6 → 6,9
.buf_pos dd ?
.buf_size dd ?
.col dq ?
.hPlugin dd ?
.hFile dd ?
.hWorkFile dd ?
.encoding db ?
.bEofReached db ?
.flags db ? ; & 1: hex mode
13,6 → 16,7
; & 4: big-endian unicode
rb 1
.filename rb 1024
.hostname rb 1024
.buf rb 16384
.size = $
end virtual
34,6 → 38,30
jnz @f
ret
@@:
mov eax, dword [esi+panel1_hPlugin-panel1_dir]
mov [ebp+viewer_data.hPlugin], eax
test eax, eax
jz .nocopyhostname
lea edi, [ebp+viewer_data.hostname]
push esi
mov eax, dword [esi+panel1_parents-panel1_dir]
mov esi, dword [esi+panel1_parents_sz-panel1_dir]
add esi, eax
@@:
dec esi
cmp byte [esi-1], 0
jz @f
cmp byte [esi-1], '/'
jnz @b
@@:
lodsb
stosb
test al, al
jnz @b
pop esi
.nocopyhostname:
mov eax, dword [esi+panel1_hFile-panel1_dir]
mov [ebp+viewer_data.hFile], eax
mov [ebp+viewer_data.encoding], encodings.cp866
mov [ebp+viewer_data.flags], 0
and dword [ebp+viewer_data.col], 0
48,6 → 76,8
jmp @b
@@:
lea esi, [ecx+40]
cmp byte [edi-1], '/'
jz @f
mov al, '/'
stosb
@@:
60,9 → 90,21
mov ebx, attrinfo
mov [ebx+21], eax
.attr_retry:
mov edx, [ebp+viewer_data.hPlugin]
test edx, edx
jz .attr_native
push ebp
push dword [ebx+16]
push eax
push [ebp+viewer_data.hFile]
call [edx+PluginInfo.getattr]
pop ebp
jmp .attr_common
.attr_native:
push 70
pop eax
int 40h
.attr_common:
test eax, eax
jz @f
lea ebx, [ebp+viewer_data.filename]
75,14 → 117,12
push 2
push eax
push 3
push -1
push -1
push aError
call SayErr
add esp, 3*4
mov ebx, attrinfo
test eax, eax
jz .attr_retry
pop eax
jmp delete_active_screen
@@:
mov eax, dword [attrinfo.attr+32]
102,7 → 142,40
mov [readinfo.data], eax
mov [ebp+viewer_data.buf_pos], eax
pop dword [readinfo.name]
mov eax, [ebp+viewer_data.hPlugin]
test eax, eax
jz .retry
push ebx ebp
push O_READ
push dword [readinfo.name]
push [ebp+viewer_data.hFile]
call [eax+PluginInfo.open]
pop ebp ebx
mov [ebp+viewer_data.hWorkFile], eax
test eax, eax
jnz .retry
push ContinueBtn
push 1
push aCannotOpenFile_ptr
push 1
call SayErr
jmp delete_active_screen
.retry:
mov eax, [ebp+viewer_data.hPlugin]
test eax, eax
jz .read_native
push ebp
push 16384
push [ebx+readinfo.data-readinfo]
push [ebp+viewer_data.hWorkFile]
call [eax+PluginInfo.read]
pop ebp
cmp eax, -1
jz .readok ; let's hope that plugin says error itself
mov [ebp+viewer_data.buf_size], eax
mov ebx, eax
jmp .readok
.read_native:
push 70
pop eax
int 40h
111,6 → 184,7
jz .readok
cmp eax, 6
jz .readok
.readerr:
lea ebx, [ebp+viewer_data.filename]
push ebx
push aCannotReadFile
121,9 → 195,6
push 2
push eax
push 3
push -1
push -1
push aError
call SayErr
add esp, 3*4
mov ebx, readinfo
194,6 → 265,21
mov [readinfo.name], eax
.readretry:
mov ebx, readinfo
mov eax, [ebp+viewer_data.hPlugin]
test eax, eax
jz .native
push ecx ebp
push 8192
push [ebx+readinfo.data-readinfo]
push [ebp+viewer_data.hWorkFile]
call [eax+PluginInfo.read]
pop ebp ecx
mov ebx, eax
cmp eax, -1
jnz .readok
xor ebx, ebx
jmp .readok
.native:
push 70
pop eax
int 40h
201,6 → 287,7
jz .readok
cmp eax, 6
jz .readok
.readerr:
call ask_retry_ignore
jz .readretry
.readok:
976,16 → 1063,7
mov [ebx+16], eax
lea eax, [ebp+viewer_data.filename]
mov [ebx+21], eax
push 70
pop eax
int 40h
test eax, eax
jz .readok
cmp eax, 6
jz .readok
call ask_retry_ignore
jz .doread
.readok:
call .q
cmp ebx, [readinfo.size]
jnz @f
add ebx, [ebp+viewer_data.buf_size]
1027,22 → 1105,47
mov [ebx+12], eax
lea eax, [ebp+viewer_data.filename]
mov [ebx+21], eax
call .q
sub ebx, [readinfo.size]
add ebx, 16384
jmp .ret
 
.q:
mov ebx, readinfo
mov eax, [ebp+viewer_data.hPlugin]
test eax, eax
jz .native
push ebp
push dword [ebx+12]
push dword [ebx+16]
push [ebp+viewer_data.hWorkFile]
push eax
push dword [ebx+8]
push dword [ebx+4]
push [ebp+viewer_data.hWorkFile]
call [eax+PluginInfo.setpos]
pop eax
call [eax+PluginInfo.read]
pop ebp
mov ebx, eax
cmp eax, -1
jnz @f
xor ebx, ebx
@@:
ret
.native:
push 70
pop eax
int 40h
test eax, eax
jz @f
jz .readok
cmp eax, 6
jz @f
jz .readok
.readerr:
call ask_retry_ignore
jnz @f
mov ebx, readinfo
jmp @b
@@:
sub ebx, [readinfo.size]
add ebx, 16384
jmp .ret
jz .q
.readok:
ret
 
ask_retry_ignore:
push esi
1056,9 → 1159,6
push 2
push eax
push 3
push -1
push -1
push aError
call SayErr
add esp, 3*4
pop esi
1268,12 → 1368,33
call viewer_draw_text
ret
 
viewer_OnExit:
mov edx, [ebp+viewer_data.hPlugin]
test edx, edx
jz @f
and [ebp+viewer_data.hPlugin], 0
push edx ebp
push [ebp+viewer_data.hWorkFile]
call [edx+PluginInfo.close]
pop ebp edx
mov ebx, [ebp+viewer_data.hFile]
call close_handle_if_unused
@@:
ret
 
viewer_IsHandleUsed:
cmp edx, [ebp+viewer_data.hPlugin]
jnz @f
cmp ebx, [ebp+viewer_data.hFile]
@@:
ret
 
viewer_OnKey:
mov esi, viewer_ctrlkeys
jmp process_ctrl_keys
.exit:
call delete_active_screen
ret
call viewer_OnExit
jmp delete_active_screen
.down:
cmp [ebp+viewer_data.bEofReached], 0
jnz .ret
1459,7 → 1580,26
stosb
end if
sub ecx, 13
cmp [ebp+viewer_data.hPlugin], 0
jz .native
lea esi, [ebp+viewer_data.hostname]
push ecx edi
shr ecx, 1
@@:
lodsb
test al, al
jz @f
stosb
loop @b
@@:
sub edi, [esp]
sub [esp+4], edi
add [esp], edi
pop edi ecx
lea esi, [ebp+viewer_data.filename]
jmp .main
.native:
lea esi, [ebp+viewer_data.filename]
push 3
pop edx
@@:
1466,10 → 1606,13
lodsb
stosb
dec ecx
test al, al
jz .ret
cmp al, '/'
jnz @b
dec edx
jnz @b
.main:
push esi
@@:
lodsb
1493,4 → 1636,5
stosb
test al, al
jnz @b
.ret:
ret