Subversion Repositories Kolibri OS

Rev

Rev 897 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 914 $
  9.  
  10.  
  11. image_of_eax EQU esp+36
  12. image_of_ebx EQU esp+24
  13.  
  14. ; System function 70 - files with long names (LFN)
  15. ; diamond, 2006
  16.  
  17. iglobal
  18. ; in this table names must be in lowercase
  19. rootdirs:
  20.         db      2,'rd'
  21.         dd      fs_OnRamdisk
  22.         dd      fs_NextRamdisk
  23.         db      7,'ramdisk'
  24.         dd      fs_OnRamdisk
  25.         dd      fs_NextRamdisk
  26.         db      2,'fd'
  27.         dd      fs_OnFloppy
  28.         dd      fs_NextFloppy
  29.         db      10,'floppydisk'
  30.         dd      fs_OnFloppy
  31.         dd      fs_NextFloppy
  32.         db      3,'hd0'
  33.         dd      fs_OnHd0
  34.         dd      fs_NextHd0
  35.         db      3,'hd1'
  36.         dd      fs_OnHd1
  37.         dd      fs_NextHd1
  38.         db      3,'hd2'
  39.         dd      fs_OnHd2
  40.         dd      fs_NextHd2
  41.         db      3,'hd3'
  42.         dd      fs_OnHd3
  43.         dd      fs_NextHd3
  44. ;**********************************************
  45.         db      3,'cd0'
  46.         dd      fs_OnCd0
  47.         dd      fs_NextCd
  48.         db      3,'cd1'
  49.         dd      fs_OnCd1
  50.         dd      fs_NextCd
  51.         db      3,'cd2'
  52.         dd      fs_OnCd2
  53.         dd      fs_NextCd
  54.         db      3,'cd3'
  55.         dd      fs_OnCd3
  56.         dd      fs_NextCd
  57. ;***********************************************
  58.         db      0
  59.  
  60.  
  61. virtual_root_query:
  62.         dd      fs_HasRamdisk
  63.         db      'rd',0
  64.         dd      fs_HasFloppy
  65.         db      'fd',0
  66.         dd      fs_HasHd0
  67.         db      'hd0',0
  68.         dd      fs_HasHd1
  69.         db      'hd1',0
  70.         dd      fs_HasHd2
  71.         db      'hd2',0
  72.         dd      fs_HasHd3
  73.         db      'hd3',0
  74. ;**********************************************
  75.         dd      fs_HasCd0
  76.         db      'cd0',0
  77.         dd      fs_HasCd1
  78.         db      'cd1',0
  79.         dd      fs_HasCd2
  80.         db      'cd2',0
  81.         dd      fs_HasCd3
  82.         db      'cd3',0
  83. ;**********************************************
  84.         dd      0
  85.  
  86. fs_additional_handlers:
  87.         dd      biosdisk_handler, biosdisk_enum_root
  88. ; add new handlers here
  89.         dd      0
  90.  
  91. endg
  92.  
  93. file_system_lfn:
  94. ; in: eax->fileinfo block
  95. ; operation codes:
  96. ; 0 : read file
  97. ; 1 : read folder
  98. ; 2 : create/rewrite file
  99. ; 3 : write/append to file
  100. ; 4 : set end of file
  101. ; 5 : get file/directory attributes structure
  102. ; 6 : set file/directory attributes structure
  103. ; 7 : start application
  104. ; 8 : delete file
  105. ; 9 : create directory
  106.  
  107.     cmp dword [eax], 7
  108.     je .do_exec
  109.  
  110. ; parse file name
  111.         xchg    ebx, eax
  112.         lea     esi, [ebx+20]
  113.         lodsb
  114.         test    al, al
  115.         jnz     @f
  116.         mov     esi, [esi]
  117.         lodsb
  118. @@:
  119.         cmp     al, '/'
  120.         jz      .notcurdir
  121.         dec     esi
  122.         mov     ebp, esi
  123.         test    al, al
  124.         jnz     @f
  125.         xor     ebp, ebp
  126. @@:
  127.         mov     esi, [current_slot]
  128.         mov     esi, [esi+APPDATA.cur_dir]
  129.         jmp     .parse_normal
  130. .notcurdir:
  131.         cmp     byte [esi], 0
  132.         jz      .rootdir
  133.         call    process_replace_file_name
  134. .parse_normal:
  135.         mov     edi, rootdirs-8
  136.         xor     ecx, ecx
  137.         push    esi
  138. .scan1:
  139.         pop     esi
  140.         add     edi, ecx
  141.         scasd
  142.         scasd
  143.         mov     cl, byte [edi]
  144.         test    cl, cl
  145.         jz      .notfound_try
  146.         inc     edi
  147.         push    esi
  148. @@:
  149.         lodsb
  150.         or      al, 20h
  151.         scasb
  152.         loopz   @b
  153.         jnz     .scan1
  154.         lodsb
  155.         cmp     al, '/'
  156.         jz      .found1
  157.         test    al, al
  158.         jnz     .scan1
  159.         pop     eax
  160. ; directory /xxx
  161. .maindir:
  162.         mov     esi, [edi+4]
  163. .maindir_noesi:
  164.         cmp     dword [ebx], 1
  165.         jnz     .access_denied
  166.         xor     eax, eax
  167.         mov     ebp, [ebx+12]
  168.         mov     edx, [ebx+16]
  169.     ;    add     edx, std_application_base_address
  170.         push    dword [ebx+4]   ; first block
  171.         mov     ebx, [ebx+8]    ; flags
  172. ; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler
  173.         mov     edi, edx
  174.         push    ecx
  175.         mov     ecx, 32/4
  176.         rep     stosd
  177.         pop     ecx
  178.         mov     byte [edx], 1   ; version
  179. .maindir_loop:
  180.         call    esi
  181.         jc      .maindir_done
  182.         inc     dword [edx+8]
  183.         dec     dword [esp]
  184.         jns     .maindir_loop
  185.         dec     ebp
  186.         js      .maindir_loop
  187.         inc     dword [edx+4]
  188.         mov     dword [edi], 0x10       ; attributes: folder
  189.         mov     dword [edi+4], 1        ; name type: UNICODE
  190.         push    eax
  191.         xor     eax, eax
  192.         add     edi, 8
  193.         push    ecx
  194.         mov     ecx, 40/4-2
  195.         rep     stosd
  196.         pop     ecx
  197.         pop     eax
  198.         push    eax edx
  199. ; convert number in eax to decimal UNICODE string
  200.         push    edi
  201.         push    ecx
  202.         push    -'0'
  203.         mov     ecx, 10
  204. @@:
  205.         xor     edx, edx
  206.         div     ecx
  207.         push    edx
  208.         test    eax, eax
  209.         jnz     @b
  210. @@:
  211.         pop     eax
  212.         add     al, '0'
  213.         stosb
  214.         test    bl, 1           ; UNICODE name?
  215.         jz      .ansi2
  216.         mov     byte [edi], 0
  217.         inc     edi
  218. .ansi2:
  219.         test    al, al
  220.         jnz     @b
  221.         mov     byte [edi-1], 0
  222.         pop     ecx
  223.         pop     edi
  224. ; UNICODE name length is 520 bytes, ANSI - 264
  225.         add     edi, 520
  226.         test    bl, 1
  227.         jnz     @f
  228.         sub     edi, 520-264
  229. @@:
  230.         pop     edx eax
  231.         jmp     .maindir_loop
  232. .maindir_done:
  233.         pop     eax
  234.         mov     ebx, [edx+4]
  235.         xor     eax, eax
  236.         dec     ebp
  237.         js      @f
  238.         mov     al, ERROR_END_OF_FILE
  239. @@:
  240.         mov     [image_of_eax], eax
  241.         mov     [image_of_ebx], ebx
  242.         ret
  243. ; directory /
  244. .rootdir:
  245.         cmp     dword [ebx], 1  ; read folder?
  246.         jz      .readroot
  247. .access_denied:
  248.         mov     dword [image_of_eax], 10      ; access denied
  249.         ret
  250.  
  251. .readroot:
  252. ; virtual root folder - special handler
  253.         mov     esi, virtual_root_query
  254.         mov     ebp, [ebx+12]
  255.         mov     edx, [ebx+16]
  256.     ;    add     edx, std_application_base_address
  257.         push    dword [ebx+4]   ; first block
  258.         mov     ebx, [ebx+8]    ; flags
  259.         xor     eax, eax
  260. ; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area
  261.         mov     edi, edx
  262.         mov     ecx, 32/4
  263.         rep     stosd
  264.         mov     byte [edx], 1   ; version
  265. .readroot_loop:
  266.         cmp     dword [esi], eax
  267.         jz      .readroot_done_static
  268.         call    dword [esi]
  269.         add     esi, 4
  270.         test    eax, eax
  271.         jnz     @f
  272. .readroot_next:
  273.         or      ecx, -1
  274.         xchg    esi, edi
  275.         repnz   scasb
  276.         xchg    esi, edi
  277.         jmp     .readroot_loop
  278. @@:
  279.         xor     eax, eax
  280.         inc     dword [edx+8]
  281.         dec     dword [esp]
  282.         jns     .readroot_next
  283.         dec     ebp
  284.         js      .readroot_next
  285.         inc     dword [edx+4]
  286.         mov     dword [edi], 0x10       ; attributes: folder
  287.         mov     dword [edi+4], ebx      ; name type: UNICODE
  288.         add     edi, 8
  289.         mov     ecx, 40/4-2
  290.         rep     stosd
  291.         push    edi
  292. @@:
  293.         lodsb
  294.         stosb
  295.         test    bl, 1
  296.         jz      .ansi
  297.         mov     byte [edi], 0
  298.         inc     edi
  299. .ansi:
  300.         test    eax, eax
  301.         jnz     @b
  302.         pop     edi
  303.         add     edi, 520
  304.         test    bl, 1
  305.         jnz     .readroot_loop
  306.         sub     edi, 520-264
  307.         jmp     .readroot_loop
  308. .readroot_done_static:
  309.         mov     esi, fs_additional_handlers-8
  310.         sub     esp, 16
  311. .readroot_ah_loop:
  312.         add     esi, 8
  313.         cmp     dword [esi], 0
  314.         jz      .readroot_done
  315.         xor     eax, eax
  316. .readroot_ah_loop2:
  317.         push    edi
  318.         lea     edi, [esp+4]
  319.         call    dword [esi+4]
  320.         pop     edi
  321.         test    eax, eax
  322.         jz      .readroot_ah_loop
  323.         inc     dword [edx+8]
  324.         dec     dword [esp+16]
  325.         jns     .readroot_ah_loop2
  326.         dec     ebp
  327.         js      .readroot_ah_loop2
  328.         push    eax
  329.         xor     eax, eax
  330.         inc     dword [edx+4]
  331.         mov     dword [edi], 0x10       ; attributes: folder
  332.         mov     dword [edi+4], ebx
  333.         add     edi, 8
  334.         mov     ecx, 40/4-2
  335.         rep     stosd
  336.         push    esi edi
  337.         lea     esi, [esp+12]
  338. @@:
  339.         lodsb
  340.         stosb
  341.         test    bl, 1
  342.         jz      .ansi3
  343.         mov     byte [edi], 0
  344.         inc     edi
  345. .ansi3:
  346.         test    al, al
  347.         jnz     @b
  348.         pop     edi esi eax
  349.         add     edi, 520
  350.         test    bl, 1
  351.         jnz     .readroot_ah_loop2
  352.         sub     edi, 520-264
  353.         jmp     .readroot_ah_loop2
  354. .readroot_done:
  355.         add     esp, 16
  356.         pop     eax
  357.         mov     ebx, [edx+4]
  358.         xor     eax, eax
  359.         dec     ebp
  360.         js      @f
  361.         mov     al, ERROR_END_OF_FILE
  362. @@:
  363.         mov     [image_of_eax], eax
  364.         mov     [image_of_ebx], ebx
  365.         ret
  366. .notfound_try:
  367.         mov     edi, fs_additional_handlers
  368. @@:
  369.         cmp     dword [edi], 0
  370.         jz      @f
  371.         call    dword [edi]
  372.         scasd
  373.         scasd
  374.         jmp     @b
  375. .notfound:
  376.         mov     dword [image_of_eax], ERROR_FILE_NOT_FOUND
  377.         and     dword [image_of_ebx], 0
  378.         ret
  379.  
  380. .notfounda:
  381.         cmp     edi, esp
  382.         jnz     .notfound
  383.         add     esp, 8
  384.         jmp     .notfound
  385.  
  386. .found1:
  387.         pop     eax
  388.         cmp     byte [esi], 0
  389.         jz      .maindir
  390. .found2:
  391. ; read partition number
  392.         xor     ecx, ecx
  393.         xor     eax, eax
  394. @@:
  395.         lodsb
  396.         cmp     al, '/'
  397.         jz      .done1
  398.         test    al, al
  399.         jz      .done1
  400.         sub     al, '0'
  401.         cmp     al, 9
  402.         ja      .notfounda
  403.         lea     ecx, [ecx*5]
  404.         lea     ecx, [ecx*2+eax]
  405.         jmp     @b
  406. .done1:
  407.         jecxz   .notfounda
  408.         test    al, al
  409.         jnz     @f
  410.         dec     esi
  411. @@:
  412.         cmp     byte [esi], 0
  413.         jnz     @f
  414.         test    ebp, ebp
  415.         jz      @f
  416.         mov     esi, ebp
  417.         xor     ebp, ebp
  418. @@:
  419. ; now [edi] contains handler address, ecx - partition number,
  420. ; esi points to ASCIIZ string - rest of name
  421.         jmp     dword [edi]
  422.  
  423. .do_exec:
  424.           lea ebx, [eax+20]
  425.           cmp byte [ebx],0
  426.           jnz @F
  427.  
  428.           mov ebx, [ebx+1]
  429. @@:
  430.           push  dword [eax+4]
  431.           push  dword [eax+8]
  432.           push  ebx
  433.  
  434.           call _sys_exec
  435.           add esp, 12
  436.           mov [image_of_eax], eax
  437.           ret
  438.  
  439.  
  440.  
  441. ; handlers for devices
  442. ; in: ecx = 0 => query virtual directory /xxx
  443. ; in: ecx = partition number
  444. ;     esi -> relative (for device) name
  445. ;     ebx -> fileinfo
  446. ;     ebp = 0 or pointer to rest of name from folder addressed by esi
  447. ; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
  448.  
  449. fs_OnRamdisk:
  450.         cmp     ecx, 1
  451.         jnz     file_system_lfn.notfound
  452.         mov     eax, [ebx]
  453.         cmp     eax, fs_NumRamdiskServices
  454.         jae     .not_impl
  455.         mov     ecx, [ebx+12]
  456.         mov     edx, [ebx+16]
  457.    ;     add     edx, std_application_base_address
  458.         add     ebx, 4
  459.         call    dword [fs_RamdiskServices + eax*4]
  460.         mov     [image_of_eax], eax
  461.         mov     [image_of_ebx], ebx
  462.         ret
  463. .not_impl:
  464.         mov     dword [image_of_eax], 2       ; not implemented
  465.         ret
  466.  
  467. fs_NotImplemented:
  468.         mov     eax, 2
  469.         ret
  470.  
  471. fs_RamdiskServices:
  472.         dd      fs_RamdiskRead
  473.         dd      fs_RamdiskReadFolder
  474.         dd      fs_RamdiskRewrite
  475.         dd      fs_RamdiskWrite
  476.         dd      fs_RamdiskSetFileEnd
  477.         dd      fs_RamdiskGetFileInfo
  478.         dd      fs_RamdiskSetFileInfo
  479.         dd      0
  480.         dd      fs_RamdiskDelete
  481.         dd      fs_RamdiskCreateFolder
  482. fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4
  483.  
  484. fs_OnFloppy:
  485.         cmp     ecx, 2
  486.         ja      file_system_lfn.notfound
  487.         mov     eax, [ebx]
  488.         cmp     eax, fs_NumFloppyServices
  489.         jae     fs_OnRamdisk.not_impl
  490.         call    reserve_flp
  491.         mov     [flp_number], cl
  492.         mov     ecx, [ebx+12]
  493.         mov     edx, [ebx+16]
  494.    ;     add     edx, std_application_base_address
  495.         add     ebx, 4
  496.         call    dword [fs_FloppyServices + eax*4]
  497.         and     [flp_status], 0
  498.         mov     [image_of_eax], eax
  499.         mov     [image_of_ebx], ebx
  500.         ret
  501.  
  502. fs_FloppyServices:
  503.         dd      fs_FloppyRead
  504.         dd      fs_FloppyReadFolder
  505.         dd      fs_FloppyRewrite
  506.         dd      fs_FloppyWrite
  507.         dd      fs_FloppySetFileEnd
  508.         dd      fs_FloppyGetFileInfo
  509.         dd      fs_FloppySetFileInfo
  510.         dd      0
  511.         dd      fs_FloppyDelete
  512.         dd      fs_FloppyCreateFolder
  513. fs_NumFloppyServices = ($ - fs_FloppyServices)/4
  514.  
  515. fs_OnHd0:
  516.         call    reserve_hd1
  517.         mov     [hdbase], 0x1F0
  518.         mov     [hdid], 0
  519.         push    1
  520.         jmp     fs_OnHd
  521. fs_OnHd1:
  522.         call    reserve_hd1
  523.         mov     [hdbase], 0x1F0
  524.         mov     [hdid], 0x10
  525.         push    2
  526.         jmp     fs_OnHd
  527. fs_OnHd2:
  528.         call    reserve_hd1
  529.         mov     [hdbase], 0x170
  530.         mov     [hdid], 0
  531.         push    3
  532.         jmp     fs_OnHd
  533. fs_OnHd3:
  534.         call    reserve_hd1
  535.         mov     [hdbase], 0x170
  536.         mov     [hdid], 0x10
  537.         push    4
  538. fs_OnHd:
  539.         call    reserve_hd_channel
  540.         pop     eax
  541.         mov     [hdpos], eax
  542.         cmp     ecx, 0x100
  543.         jae     fs_OnHdAndBd.nf
  544.         cmp     cl, [DRIVE_DATA+1+eax]
  545. fs_OnHdAndBd:
  546.         jbe     @f
  547. .nf:
  548.         call    free_hd_channel
  549.         and     [hd1_status], 0
  550.         mov     dword [image_of_eax], 5       ; not found
  551.         ret
  552. @@:
  553.         mov     [fat32part], ecx
  554.         push    ebx esi
  555.         call    choice_necessity_partition_1
  556.         pop     esi ebx
  557.         mov     ecx, [ebx+12]
  558.         mov     edx, [ebx+16]
  559.     ;    add     edx, std_application_base_address
  560.         mov     eax, [ebx]
  561.         cmp     eax, fs_NumHdServices
  562.         jae     .not_impl
  563.         add     ebx, 4
  564.         call    dword [fs_HdServices + eax*4]
  565.         call    free_hd_channel
  566.         and     [hd1_status], 0
  567.         mov     [image_of_eax], eax
  568.         mov     [image_of_ebx], ebx
  569.         ret
  570. .not_impl:
  571.         call    free_hd_channel
  572.         and     [hd1_status], 0
  573.         mov     dword [image_of_eax], 2       ; not implemented
  574.         ret
  575.  
  576. fs_HdServices:
  577.         dd      fs_HdRead
  578.         dd      fs_HdReadFolder
  579.         dd      fs_HdRewrite
  580.         dd      fs_HdWrite
  581.         dd      fs_HdSetFileEnd
  582.         dd      fs_HdGetFileInfo
  583.         dd      fs_HdSetFileInfo
  584.         dd      0
  585.         dd      fs_HdDelete
  586.         dd      fs_HdCreateFolder
  587. fs_NumHdServices = ($ - fs_HdServices)/4
  588.  
  589. ;*******************************************************
  590. fs_OnCd0:
  591.         call    reserve_cd
  592.         mov  [ChannelNumber],1
  593.         mov  [DiskNumber],0
  594.         push    6
  595.         push    1
  596.         jmp     fs_OnCd
  597. fs_OnCd1:
  598.         call    reserve_cd
  599.         mov  [ChannelNumber],1
  600.         mov  [DiskNumber],1
  601.         push    4
  602.         push    2
  603.         jmp     fs_OnCd
  604. fs_OnCd2:
  605.         call    reserve_cd
  606.         mov  [ChannelNumber],2
  607.         mov  [DiskNumber],0
  608.         push    2
  609.         push    3
  610.         jmp     fs_OnCd
  611. fs_OnCd3:
  612.         call    reserve_cd
  613.         mov  [ChannelNumber],2
  614.         mov  [DiskNumber],1
  615.         push    0
  616.         push    4
  617. fs_OnCd:
  618.         call    reserve_cd_channel
  619.         pop     eax
  620.         mov     [cdpos], eax
  621.         pop     eax
  622.         cmp     ecx, 0x100
  623.         jae     .nf
  624.         push    ecx ebx
  625.         mov     cl,al
  626.         mov     bl,[DRIVE_DATA+1]
  627.         shr     bl,cl
  628.         test    bl,2
  629.         pop     ebx ecx
  630.  
  631.         jnz     @f
  632. .nf:
  633.         call    free_cd_channel
  634.         and    [cd_status], 0
  635.         mov     dword [image_of_eax], 5       ; not found
  636.         ret
  637. @@:
  638.         mov     ecx, [ebx+12]
  639.         mov     edx, [ebx+16]
  640.     ;    add     edx, std_application_base_address
  641.         mov     eax, [ebx]
  642.         cmp     eax,fs_NumCdServices
  643.         jae      .not_impl
  644.         add     ebx, 4
  645.         call    dword [fs_CdServices + eax*4]
  646.         call    free_cd_channel
  647.         and     [cd_status], 0
  648.         mov     [image_of_eax], eax
  649.         mov     [image_of_ebx], ebx
  650.         ret
  651. .not_impl:
  652.         call    free_cd_channel
  653.         and     [cd_status], 0
  654.         mov     dword [image_of_eax], 2       ; not implemented
  655.         ret
  656.  
  657. fs_CdServices:
  658.         dd      fs_CdRead
  659.         dd      fs_CdReadFolder
  660.         dd      fs_NotImplemented
  661.         dd      fs_NotImplemented
  662.         dd      fs_NotImplemented
  663.         dd      fs_CdGetFileInfo
  664.         dd      fs_NotImplemented
  665.         dd      0
  666.         dd      fs_NotImplemented
  667.         dd      fs_NotImplemented
  668. fs_NumCdServices = ($ - fs_CdServices)/4
  669.  
  670. ;*******************************************************
  671.  
  672. fs_HasRamdisk:
  673.         mov     al, 1   ; we always have ramdisk
  674.         ret
  675.  
  676. fs_HasFloppy:
  677.         cmp     byte [DRIVE_DATA], 0
  678.         setnz   al
  679.         ret
  680.  
  681. fs_HasHd0:
  682.         mov     al, [DRIVE_DATA+1]
  683.         and     al, 11000000b
  684.         cmp     al, 01000000b
  685.         setz    al
  686.         ret
  687. fs_HasHd1:
  688.         mov     al, [DRIVE_DATA+1]
  689.         and     al, 00110000b
  690.         cmp     al, 00010000b
  691.         setz    al
  692.         ret
  693. fs_HasHd2:
  694.         mov     al, [DRIVE_DATA+1]
  695.         and     al, 00001100b
  696.         cmp     al, 00000100b
  697.         setz    al
  698.         ret
  699. fs_HasHd3:
  700.         mov     al, [DRIVE_DATA+1]
  701.         and     al, 00000011b
  702.         cmp     al, 00000001b
  703.         setz    al
  704.         ret
  705.  
  706. ;*******************************************************
  707. fs_HasCd0:
  708.         mov     al, [DRIVE_DATA+1]
  709.         and     al, 11000000b
  710.         cmp     al, 10000000b
  711.         setz    al
  712.         ret
  713. fs_HasCd1:
  714.         mov     al, [DRIVE_DATA+1]
  715.         and     al, 00110000b
  716.         cmp     al, 00100000b
  717.         setz    al
  718.         ret
  719. fs_HasCd2:
  720.         mov     al, [DRIVE_DATA+1]
  721.         and     al, 00001100b
  722.         cmp     al, 00001000b
  723.         setz    al
  724.         ret
  725. fs_HasCd3:
  726.         mov     al, [DRIVE_DATA+1]
  727.         and     al, 00000011b
  728.         cmp     al, 00000010b
  729.         setz    al
  730.         ret
  731. ;*******************************************************
  732.  
  733. ; fs_NextXXX functions:
  734. ; in: eax = partition number, from which start to scan
  735. ; out: CF=1 => no more partitions
  736. ;      CF=0 => eax=next partition number
  737.  
  738. fs_NextRamdisk:
  739. ; we always have /rd/1
  740.         test    eax, eax
  741.         stc
  742.         jnz     @f
  743.         mov     al, 1
  744.         clc
  745. @@:
  746.         ret
  747.  
  748. fs_NextFloppy:
  749. ; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0)
  750.         test    byte [DRIVE_DATA], 0xF0
  751.         jz      .no1
  752.         test    eax, eax
  753.         jnz     .no1
  754.         inc     eax
  755.         ret     ; CF cleared
  756. .no1:
  757.         test    byte [DRIVE_DATA], 0x0F
  758.         jz      .no2
  759.         cmp     al, 2
  760.         jae     .no2
  761.         mov     al, 2
  762.         clc
  763.         ret
  764. .no2:
  765.         stc
  766.         ret
  767.  
  768. ; on hdx, we have partitions from 1 to [0x40002+x]
  769. fs_NextHd0:
  770.         push    0
  771.         jmp     fs_NextHd
  772. fs_NextHd1:
  773.         push    1
  774.         jmp     fs_NextHd
  775. fs_NextHd2:
  776.         push    2
  777.         jmp     fs_NextHd
  778. fs_NextHd3:
  779.         push    3
  780. fs_NextHd:
  781.         pop     ecx
  782.         movzx   ecx, byte [DRIVE_DATA+2+ecx]
  783.         cmp     eax, ecx
  784.         jae     fs_NextFloppy.no2
  785.         inc     eax
  786.         clc
  787.         ret
  788.  
  789. ;*******************************************************
  790. fs_NextCd:
  791. ; we always have /cdX/1
  792.         test    eax, eax
  793.         stc
  794.         jnz     @f
  795.         mov     al, 1
  796.         clc
  797. @@:
  798.         ret
  799. ;*******************************************************
  800.  
  801. ; Additional FS handlers.
  802. ; This handler gets the control each time when fn 70 is called
  803. ; with unknown item of root subdirectory.
  804. ; in: esi -> name
  805. ;     ebp = 0 or rest of name relative to esi
  806. ; out: if the handler processes path, he must not return in file_system_lfn,
  807. ;      but instead pop return address and return directly to the caller
  808. ;      otherwise simply return
  809.  
  810. ; here we test for /bd<N>/... - BIOS disks
  811. biosdisk_handler:
  812.         cmp     [NumBiosDisks], 0
  813.         jz      .ret
  814.         mov     al, [esi]
  815.         or      al, 20h
  816.         cmp     al, 'b'
  817.         jnz     .ret
  818.         mov     al, [esi+1]
  819.         or      al, 20h
  820.         cmp     al, 'd'
  821.         jnz     .ret
  822.         push    esi
  823.         inc     esi
  824.         inc     esi
  825.         cmp     byte [esi], '0'
  826.         jb      .ret2
  827.         cmp     byte [esi], '9'
  828.         ja      .ret2
  829.         xor     edx, edx
  830. @@:
  831.         lodsb
  832.         test    al, al
  833.         jz      .ok
  834.         cmp     al, '/'
  835.         jz      .ok
  836.         sub     al, '0'
  837.         cmp     al, 9
  838.         ja      .ret2
  839.         lea     edx, [edx*5]
  840.         lea     edx, [edx*2+eax]
  841.         jmp     @b
  842. .ret2:
  843.         pop     esi
  844. .ret:
  845.         ret
  846. .ok:
  847.         cmp     al, '/'
  848.         jz      @f
  849.         dec     esi
  850. @@:
  851.         add     dl, 80h
  852.         xor     ecx, ecx
  853. @@:
  854.         cmp     dl, [BiosDisksData+ecx*4]
  855.         jz      .ok2
  856.         inc     ecx
  857.         cmp     ecx, [NumBiosDisks]
  858.         jb      @b
  859.         jmp     .ret2
  860. .ok2:
  861.         add     esp, 8
  862.         test    al, al
  863.         jnz     @f
  864.         mov     esi, fs_BdNext
  865.         jmp     file_system_lfn.maindir_noesi
  866. @@:
  867.         push    ecx
  868.         push    fs_OnBd
  869.         mov     edi, esp
  870.         jmp     file_system_lfn.found2
  871.  
  872. fs_BdNext:
  873.         cmp     eax, [BiosDiskPartitions+ecx*4]
  874.         inc     eax
  875.         cmc
  876.         ret
  877.  
  878. fs_OnBd:
  879.         pop     edx edx
  880. ; edx = disk number, ecx = partition number
  881. ; esi+ebp = name
  882.         call    reserve_hd1
  883.         add     edx, 0x80
  884.         mov     [hdpos], edx
  885.         cmp     ecx, [BiosDiskPartitions+(edx-0x80)*4]
  886.         jmp     fs_OnHdAndBd
  887.  
  888. ; This handler is called when virtual root is enumerated
  889. ; and must return all items which can be handled by this.
  890. ; It is called several times, first time with eax=0
  891. ; in: eax = 0 for first call, previously returned value for subsequent calls
  892. ; out: eax = 0 => no more items
  893. ;      eax != 0 => buffer pointed to by edi contains name of item
  894.  
  895. ; here we enumerate existing BIOS disks /bd<N>
  896. biosdisk_enum_root:
  897.         cmp     eax, [NumBiosDisks]
  898.         jae     .end
  899.         push    eax
  900.         movzx   eax, byte [BiosDisksData+eax*4]
  901.         sub     al, 80h
  902.         push    eax
  903.         mov     al, 'b'
  904.         stosb
  905.         mov     al, 'd'
  906.         stosb
  907.         pop     eax
  908.         cmp     al, 10
  909.         jae     .big
  910.         add     al, '0'
  911.         stosb
  912.         mov     byte [edi], 0
  913.         pop     eax
  914.         inc     eax
  915.         ret
  916. .end:
  917.         xor     eax, eax
  918.         ret
  919. .big:
  920.         push    ecx
  921.         push    -'0'
  922.         mov     ecx, 10
  923. @@:
  924.         xor     edx, edx
  925.         div     ecx
  926.         push    edx
  927.         test    eax, eax
  928.         jnz     @b
  929.         xchg    eax, edx
  930. @@:
  931.         pop     eax
  932.         add     al, '0'
  933.         stosb
  934.         jnz     @b
  935.         pop     ecx
  936.         pop     eax
  937.         inc     eax
  938.         ret
  939.  
  940. process_replace_file_name:
  941.         mov     ebp, [full_file_name_table]
  942.         mov     edi, [full_file_name_table.size]
  943.         dec     edi
  944.         shl     edi, 7
  945.         add     edi, ebp
  946. .loop:
  947.         cmp     edi, ebp
  948.         jb      .notfound
  949.         push    esi edi
  950. @@:
  951.         cmp     byte [edi], 0
  952.         jz      .dest_done
  953.         lodsb
  954.         test    al, al
  955.         jz      .cont
  956.         or      al, 20h
  957.         scasb
  958.         jz      @b
  959.         jmp     .cont
  960. .dest_done:
  961.         cmp     byte [esi], 0
  962.         jz      .found
  963.         cmp     byte [esi], '/'
  964.         jnz     .cont
  965.         inc     esi
  966.         jmp     .found
  967. .cont:
  968.         pop     edi esi
  969.         sub     edi, 128
  970.         jmp     .loop
  971. .found:
  972.         pop     edi eax
  973.         mov     ebp, esi
  974.         cmp     byte [esi], 0
  975.         lea     esi, [edi+64]
  976.         jnz     .ret
  977. .notfound:
  978.         xor     ebp, ebp
  979. .ret:
  980.         ret
  981.  
  982. sys_current_directory:
  983.         mov     esi, [current_slot]
  984.         mov     esi, [esi+APPDATA.cur_dir]
  985.         mov     edx, esi
  986.         dec     eax
  987.         jz      .set
  988.         dec     eax
  989.         jz      .get
  990.         ret
  991. .get:
  992. ; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
  993. ; for our code: ebx->buffer,ecx=len
  994. @@:
  995.         lodsb
  996.         test    al, al
  997.         jnz     @b
  998.         sub     esi, edx
  999.         inc     esi
  1000.         mov     [esp+36], esi
  1001.         cmp     ecx, esi
  1002.         jbe     @f
  1003.         mov     ecx, esi
  1004. @@:
  1005.         cmp     ecx, 1
  1006.         jbe     .ret
  1007.         mov     esi, edx
  1008.         mov     edi, ebx
  1009.         mov     al, '/'
  1010.         stosb
  1011.         dec     ecx
  1012.         dec     ecx
  1013.         rep     movsb
  1014.         mov     byte [edi], 0
  1015. .ret:
  1016.         ret
  1017. .set:
  1018. ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
  1019. ; for our code: ebx->string to set
  1020. @@:
  1021.         inc     esi
  1022.         cmp     byte [esi-1], 0
  1023.         jnz     @b
  1024.         dec     esi
  1025.         cmp     byte [ebx], '/'
  1026.         jz      .set_absolute
  1027. ; string gives relative path
  1028. .relative:
  1029.         cmp     byte [ebx], 0
  1030.         jz      .set_ok
  1031.         cmp     word [ebx], '.'
  1032.         jz      .set_ok
  1033.         cmp     word [ebx], './'
  1034.         jnz     @f
  1035.         add     ebx, 2
  1036.         jmp     .relative
  1037. @@:
  1038.         cmp     word [ebx], '..'
  1039.         jnz     .doset_relative
  1040.         cmp     byte [ebx+2], 0
  1041.         jz      @f
  1042.         cmp     byte [ebx+2], '/'
  1043.         jnz     .doset_relative
  1044. @@:
  1045.         dec     esi
  1046.         cmp     byte [esi], '/'
  1047.         jnz     @b
  1048.         mov     byte [esi], 0
  1049.         add     ebx, 3
  1050.         jmp     .relative
  1051. .doset_relative:
  1052.         add     edx, 0x1000
  1053.         mov     byte [esi], '/'
  1054.         inc     esi
  1055.         cmp     esi, edx
  1056.         jae     .overflow_esi
  1057. @@:
  1058.         mov     al, [ebx]
  1059.         inc     ebx
  1060.         mov     [esi], al
  1061.         inc     esi
  1062.         test    al, al
  1063.         jz      .set_ok
  1064.         cmp     esi, edx
  1065.         jb      @b
  1066. .overflow_esi:
  1067.         mov     byte [esi-1], 0         ; force null-terminated string
  1068. .set_ok:
  1069.         ret
  1070. .set_absolute:
  1071.         lea     esi, [ebx+1]
  1072.         call    process_replace_file_name
  1073.         mov     edi, edx
  1074.         add     edx, 0x1000
  1075. .set_copy:
  1076.         lodsb
  1077.         stosb
  1078.         test    al, al
  1079.         jz      .set_part2
  1080. .set_copy_cont:
  1081.         cmp     edi, edx
  1082.         jb      .set_copy
  1083. .overflow_edi:
  1084.         mov     byte [edi-1], 0
  1085.         ret
  1086. .set_part2:
  1087.         mov     esi, ebp
  1088.         xor     ebp, ebp
  1089.         test    esi, esi
  1090.         jz      .set_ok
  1091.         mov     byte [edi-1], '/'
  1092.         jmp     .set_copy_cont
  1093.