;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ uglobal cd_current_pointer_of_input dd 0 cd_current_pointer_of_input_2 dd 0 cd_mem_location dd 0 cd_counter_block dd 0 IDE_Channel_1 db 0 IDE_Channel_2 db 0 endg reserve_cd: cli cmp [cd_status], 0 je reserve_ok2 sti call change_task jmp reserve_cd reserve_ok2: push eax mov eax, [CURRENT_TASK] shl eax, 5 mov eax, [eax+CURRENT_TASK+TASKDATA.pid] mov [cd_status], eax pop eax sti ret reserve_cd_channel: cmp [ChannelNumber], 1 jne .IDE_Channel_2 .IDE_Channel_1: cli cmp [IDE_Channel_1], 0 je .reserve_ok_1 sti call change_task jmp .IDE_Channel_1 .IDE_Channel_2: cli cmp [IDE_Channel_2], 0 je .reserve_ok_2 sti call change_task jmp .IDE_Channel_2 .reserve_ok_1: mov [IDE_Channel_1], 1 sti ret .reserve_ok_2: mov [IDE_Channel_2], 1 sti ret free_cd_channel: cmp [ChannelNumber], 1 jne .IDE_Channel_2 .IDE_Channel_1: mov [IDE_Channel_1], 0 sti ret .IDE_Channel_2: mov [IDE_Channel_2], 0 sti ret uglobal cd_status dd 0 endg ;---------------------------------------------------------------- ; ; fs_CdRead - LFN variant for reading CD disk ; ; esi points to filename /dir1/dir2/.../dirn/file,0 ; ebx pointer to 64-bit number = first wanted byte, 0+ ; may be ebx=0 - start from first byte ; ecx number of bytes to read, 0+ ; edx mem location to return data ; ; ret ebx = bytes read or 0xffffffff file not found ; eax = 0 ok read or other = errormsg ; ;-------------------------------------------------------------- fs_CdRead: push edi cmp byte [esi], 0 jnz @f .noaccess: pop edi .noaccess_2: or ebx, -1 mov eax, ERROR_ACCESS_DENIED ret .noaccess_3: pop eax edx ecx edi jmp .noaccess_2 @@: call cd_find_lfn jnc .found pop edi cmp [DevErrorCode], 0 jne .noaccess_2 or ebx, -1 mov eax, ERROR_FILE_NOT_FOUND ret .found: mov edi, [cd_current_pointer_of_input] test byte [edi+25], 10b; do not allow read directories jnz .noaccess test ebx, ebx jz .l1 cmp dword [ebx+4], 0 jz @f xor ebx, ebx .reteof: mov eax, 6; end of file pop edi ret @@: mov ebx, [ebx] .l1: push ecx edx push 0 mov eax, [edi+10] ; �������� ������ �������� ������ sub eax, ebx jb .eof cmp eax, ecx jae @f mov ecx, eax mov byte [esp], 6 @@: mov eax, [edi+2] mov [CDSectorAddress], eax ; now eax=cluster, ebx=position, ecx=count, edx=buffer for data .new_sector: test ecx, ecx jz .done sub ebx, 2048 jae .next add ebx, 2048 jnz .incomplete_sector cmp ecx, 2048 jb .incomplete_sector ; we may read and memmove complete sector mov [CDDataBuf_pointer], edx call ReadCDWRetr; ������ ������ ����� cmp [DevErrorCode], 0 jne .noaccess_3 add edx, 2048 sub ecx, 2048 .next: inc dword [CDSectorAddress] jmp .new_sector .incomplete_sector: ; we must read and memmove incomplete sector mov [CDDataBuf_pointer], CDDataBuf call ReadCDWRetr; ������ ������ ����� cmp [DevErrorCode], 0 jne .noaccess_3 push ecx add ecx, ebx cmp ecx, 2048 jbe @f mov ecx, 2048 @@: sub ecx, ebx push edi esi ecx mov edi, edx lea esi, [CDDataBuf + ebx] cld rep movsb pop ecx esi edi add edx, ecx sub [esp], ecx pop ecx xor ebx, ebx jmp .next .done: mov ebx, edx pop eax edx ecx edi sub ebx, edx ret .eof: mov ebx, edx pop eax edx ecx sub ebx, edx jmp .reteof ;---------------------------------------------------------------- ; ; fs_CdReadFolder - LFN variant for reading CD disk folder ; ; esi points to filename /dir1/dir2/.../dirn/file,0 ; ebx pointer to structure 32-bit number = first wanted block, 0+ ; & flags (bitfields) ; flags: bit 0: 0=ANSI names, 1=UNICODE names ; ecx number of blocks to read, 0+ ; edx mem location to return data ; ; ret ebx = blocks read or 0xffffffff folder not found ; eax = 0 ok read or other = errormsg ; ;-------------------------------------------------------------- fs_CdReadFolder: push edi call cd_find_lfn jnc .found pop edi cmp [DevErrorCode], 0 jne .noaccess_1 or ebx, -1 mov eax, ERROR_FILE_NOT_FOUND ret .found: mov edi, [cd_current_pointer_of_input] test byte [edi+25], 10b ; do not allow read directories jnz .found_dir pop edi .noaccess_1: or ebx, -1 mov eax, ERROR_ACCESS_DENIED ret .found_dir: mov eax, [edi+2] ; eax=cluster mov [CDSectorAddress], eax mov eax, [edi+10] ; ������ ����������� .doit: ; init header push eax ecx mov edi, edx mov ecx, 32/4 xor eax, eax rep stosd pop ecx eax mov byte [edx], 1 ; version mov [cd_mem_location], edx add [cd_mem_location], 32 ; �������� ���������� ���� � ���� ;.mainloop: mov [cd_counter_block], dword 0 dec dword [CDSectorAddress] push ecx .read_to_buffer: inc dword [CDSectorAddress] mov [CDDataBuf_pointer], CDDataBuf call ReadCDWRetr ; ������ ������ ���������� cmp [DevErrorCode], 0 jne .noaccess_1 call .get_names_from_buffer sub eax, 2048 ; ���������� �����������? ja .read_to_buffer mov edi, [cd_counter_block] mov [edx+8], edi mov edi, [ebx] sub [edx+4], edi xor eax, eax dec ecx js @f mov al, ERROR_END_OF_FILE @@: pop ecx edi mov ebx, [edx+4] ret .get_names_from_buffer: mov [cd_current_pointer_of_input_2], CDDataBuf push eax esi edi edx .get_names_from_buffer_1: call cd_get_name jc .end_buffer inc dword [cd_counter_block] mov eax, [cd_counter_block] cmp [ebx], eax jae .get_names_from_buffer_1 test ecx, ecx jz .get_names_from_buffer_1 mov edi, [cd_counter_block] mov [edx+4], edi dec ecx mov esi, ebp mov edi, [cd_mem_location] add edi, 40 test dword [ebx+4], 1; 0=ANSI, 1=UNICODE jnz .unicode ; jmp .unicode .ansi: cmp [cd_counter_block], 2 jbe .ansi_parent_directory cld lodsw xchg ah, al call uni2ansi_char cld stosb ; �������� ����� ����� mov ax, [esi] cmp ax, word 3B00h; ��������� ����� ����� ';' je .cd_get_parameters_of_file_1 ; �������� ��� ������ �� ��������������� ����������� movzx eax, byte [ebp-33] add eax, ebp sub eax, 34 cmp esi, eax je .cd_get_parameters_of_file_1 ; �������� ����� ����� movzx eax, byte [ebp-1] add eax, ebp cmp esi, eax jb .ansi .cd_get_parameters_of_file_1: mov [edi], byte 0 call cd_get_parameters_of_file add [cd_mem_location], 304 jmp .get_names_from_buffer_1 .ansi_parent_directory: cmp [cd_counter_block], 2 je @f mov [edi], byte '.' inc edi jmp .cd_get_parameters_of_file_1 @@: mov [edi], word '..' add edi, 2 jmp .cd_get_parameters_of_file_1 .unicode: cmp [cd_counter_block], 2 jbe .unicode_parent_directory cld movsw ; �������� ����� ����� mov ax, [esi] cmp ax, word 3B00h; ��������� ����� ����� ';' je .cd_get_parameters_of_file_2 ; �������� ��� ������ �� ��������������� ����������� movzx eax, byte [ebp-33] add eax, ebp sub eax, 34 cmp esi, eax je .cd_get_parameters_of_file_2 ; �������� ����� ����� movzx eax, byte [ebp-1] add eax, ebp cmp esi, eax jb .unicode .cd_get_parameters_of_file_2: mov [edi], word 0 call cd_get_parameters_of_file add [cd_mem_location], 560 jmp .get_names_from_buffer_1 .unicode_parent_directory: cmp [cd_counter_block], 2 je @f mov [edi], word 2E00h; '.' add edi, 2 jmp .cd_get_parameters_of_file_2 @@: mov [edi], dword 2E002E00h; '..' add edi, 4 jmp .cd_get_parameters_of_file_2 .end_buffer: pop edx edi esi eax ret cd_get_parameters_of_file: mov edi, [cd_mem_location] cd_get_parameters_of_file_1: ; �������� �������� ����� xor eax, eax ; ���� �� ������������� inc eax shl eax, 1 ; ��� �������? test [ebp-8], byte 2 jz .file inc eax .file: ; ����� ���� �� ��� � FAT, � ���� ���� ���������� ; ���� �� �������� ��������� shl eax, 3 ; ���� �������� �������? (������� �������������) test [ebp-8], byte 1 jz .hidden inc eax .hidden: shl eax, 1 ; ���� ������ ������ ��� ������, ��� ��� ��� CD inc eax mov [edi], eax ; �������� ����� ��� ����� ;��� movzx eax, byte [ebp-12] shl eax, 8 ;������ mov al, [ebp-11] shl eax, 8 ;������� mov al, [ebp-10] ;����� �������� ����� mov [edi+8], eax ;����� ���������� ������� mov [edi+16], eax ;����� ��������� ������ mov [edi+24], eax ; �������� ���� ��� ����� ;��� movzx eax, byte [ebp-15] add eax, 1900 shl eax, 8 ;����� mov al, [ebp-14] shl eax, 8 ;���� mov al, [ebp-13] ;���� �������� ����� mov [edi+12], eax ;����� ���������� ������� mov [edi+20], eax ;����� ��������� ������ mov [edi+28], eax ; �������� ��� ������ ����� xor eax, eax test dword [ebx+4], 1; 0=ANSI, 1=UNICODE jnz .unicode_1 mov [edi+4], eax jmp @f .unicode_1: inc eax mov [edi+4], eax @@: ; �������� ������ ����� � ������ xor eax, eax mov [edi+32+4], eax mov eax, [ebp-23] mov [edi+32], eax ret ;---------------------------------------------------------------- ; ; fs_CdGetFileInfo - LFN variant for CD ; get file/directory attributes structure ; ;---------------------------------------------------------------- fs_CdGetFileInfo: cmp byte [esi], 0 jnz @f mov eax, 2 ret @@: push edi call cd_find_lfn pushfd cmp [DevErrorCode], 0 jz @f popfd pop edi mov eax, 11 ret @@: popfd jnc @f pop edi mov eax, ERROR_FILE_NOT_FOUND ret @@: mov edi, edx push ebp mov ebp, [cd_current_pointer_of_input] add ebp, 33 call cd_get_parameters_of_file_1 pop ebp and dword [edi+4], 0 pop edi xor eax, eax ret ;---------------------------------------------------------------- cd_find_lfn: mov [cd_appl_data], 0 ; in: esi+ebp -> name ; out: CF=1 - file not found ; else CF=0 and [cd_current_pointer_of_input] direntry push eax esi ; 16 ������ ������ ������ ������������ ����� call WaitUnitReady cmp [DevErrorCode], 0 jne .access_denied call prevent_medium_removal ; �������� ������ mov [CDSectorAddress], dword 16 mov [CDDataBuf_pointer], CDDataBuf call ReadCDWRetr;_1 cmp [DevErrorCode], 0 jne .access_denied ; ���������� ��������� ������ call WaitUnitReady cmp [DevErrorCode], 0 jne .access_denied call Read_TOC mov ah, [CDDataBuf+4+4] mov al, [CDDataBuf+4+5] shl eax, 16 mov ah, [CDDataBuf+4+6] mov al, [CDDataBuf+4+7] add eax, 15 mov [CDSectorAddress], eax ; mov [CDSectorAddress],dword 15 mov [CDDataBuf_pointer], CDDataBuf .start: inc dword [CDSectorAddress] call ReadCDWRetr;_1 cmp [DevErrorCode], 0 jne .access_denied .start_check: ; �������� �� �������� cmp [CDDataBuf+1], dword 'CD00' jne .access_denied cmp [CDDataBuf+5], byte '1' jne .access_denied ; ������ �������� ������������ ����� ������������ �����? cmp [CDDataBuf], byte 0xff je .access_denied ; ������ �������� �������������� � ���������� ������������ ����? cmp [CDDataBuf], byte 0x2 jne .start ; ������ �������� �������������� ������������ ����? cmp [CDDataBuf+6], byte 0x1 jne .start ; ��������� root ����������� mov eax, [CDDataBuf+0x9c+2]; ������ root ����������� mov [CDSectorAddress], eax mov eax, [CDDataBuf+0x9c+10]; ������ root ����������� cmp byte [esi], 0 jnz @f mov [cd_current_pointer_of_input], CDDataBuf+0x9c jmp .done @@: ; �������� ����� .mainloop: dec dword [CDSectorAddress] .read_to_buffer: inc dword [CDSectorAddress] mov [CDDataBuf_pointer], CDDataBuf call ReadCDWRetr ; ������ ������ ���������� cmp [DevErrorCode], 0 jne .access_denied push ebp call cd_find_name_in_buffer pop ebp jnc .found sub eax, 2048 ; ���������� �����������? cmp eax, 0 ja .read_to_buffer ; ��� �������� �������� ������� .access_denied: pop esi eax mov [cd_appl_data], 1 stc ret ; ������� ������� ������� ������ .found: ; ����� ���� ����� cmp byte [esi-1], 0 jz .done .nested: mov eax, [cd_current_pointer_of_input] push dword [eax+2] pop dword [CDSectorAddress] ; ������ ���������� mov eax, [eax+2+8]; ������ ���������� jmp .mainloop ; ��������� ����� ������ .done: test ebp, ebp jz @f mov esi, ebp xor ebp, ebp jmp .nested @@: pop esi eax mov [cd_appl_data], 1 clc ret cd_find_name_in_buffer: mov [cd_current_pointer_of_input_2], CDDataBuf .start: call cd_get_name jc .not_found call cd_compare_name jc .start .found: clc ret .not_found: stc ret cd_get_name: push eax mov ebp, [cd_current_pointer_of_input_2] mov [cd_current_pointer_of_input], ebp mov eax, [ebp] test eax, eax ; ����� �����������? jz .next_sector cmp ebp, CDDataBuf+2048 ; ����� ����������? jae .next_sector movzx eax, byte [ebp] add [cd_current_pointer_of_input_2], eax; ��������� ���� �������� add ebp, 33; ��������� ���������� �� ������ ����� pop eax clc ret .next_sector: pop eax stc ret cd_compare_name: ; compares ASCIIZ-names, case-insensitive (cp866 encoding) ; in: esi->name, ebp->name ; out: if names match: ZF=1 and esi->next component of name ; else: ZF=0, esi is not changed ; destroys eax push esi eax edi mov edi, ebp .loop: cld lodsb push eax call char_todown call ansi2uni_char xchg ah, al scasw pop eax je .coincides call char_toupper call ansi2uni_char xchg ah, al sub edi, 2 scasw jne .name_not_coincide .coincides: cmp [esi], byte '/'; ����������� ����, ����� ����� �������� �������� je .done cmp [esi], byte 0; ����������� ����, ����� ����� �������� �������� je .done jmp .loop .name_not_coincide: pop edi eax esi stc ret .done: ; �������� ����� ����� cmp [edi], word 3B00h; ��������� ����� ����� ';' je .done_1 ; �������� ��� ������ �� ��������������� ����������� movzx eax, byte [ebp-33] add eax, ebp sub eax, 34 cmp edi, eax je .done_1 ; �������� ����� ����� movzx eax, byte [ebp-1] add eax, ebp cmp edi, eax jne .name_not_coincide .done_1: pop edi eax add esp, 4 inc esi clc ret char_todown: ; convert character to uppercase, using cp866 encoding ; in: al=symbol ; out: al=converted symbol cmp al, 'A' jb .ret cmp al, 'Z' jbe .az cmp al, '�' jb .ret cmp al, '�' jb .rus1 cmp al, '�' ja .ret ; 0x90-0x9F -> 0xE0-0xEF add al, '�'-'�' .ret: ret .rus1: ; 0x80-0x8F -> 0xA0-0xAF .az: add al, 0x20 ret uni2ansi_char: ; convert UNICODE character in al to ANSI character in ax, using cp866 encoding ; in: ax=UNICODE character ; out: al=converted ANSI character cmp ax, 0x80 jb .ascii 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: mov al, '_' jmp .doit .yo1: mov al, '�' jmp .doit .yo2: mov al, '�' jmp .doit .rus1: ; 0x410-0x43F -> 0x80-0xAF add al, 0x70 jmp .doit .rus2: ; 0x440-0x44F -> 0xE0-0xEF add al, 0xA0 .ascii: .doit: ret