Subversion Repositories Kolibri OS

Rev

Rev 837 | Go to most recent revision | 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: 897 $
  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.           mov [image_of_eax], eax
  436.           add esp, 12
  437.  
  438.           ret
  439.  
  440. ; handlers for devices
  441. ; in: ecx = 0 => query virtual directory /xxx
  442. ; in: ecx = partition number
  443. ;     esi -> relative (for device) name
  444. ;     ebx -> fileinfo
  445. ;     ebp = 0 or pointer to rest of name from folder addressed by esi
  446. ; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
  447.  
  448. fs_OnRamdisk:
  449.         cmp     ecx, 1
  450.         jnz     file_system_lfn.notfound
  451.         mov     eax, [ebx]
  452.         cmp     eax, fs_NumRamdiskServices
  453.         jae     .not_impl
  454.         mov     ecx, [ebx+12]
  455.         mov     edx, [ebx+16]
  456.    ;     add     edx, std_application_base_address
  457.         add     ebx, 4
  458.         call    dword [fs_RamdiskServices + eax*4]
  459.         mov     [image_of_eax], eax
  460.         mov     [image_of_ebx], ebx
  461.         ret
  462. .not_impl:
  463.         mov     dword [image_of_eax], 2       ; not implemented
  464.         ret
  465.  
  466. fs_NotImplemented:
  467.         mov     eax, 2
  468.         ret
  469.  
  470. fs_RamdiskServices:
  471.         dd      fs_RamdiskRead
  472.         dd      fs_RamdiskReadFolder
  473.         dd      fs_RamdiskRewrite
  474.         dd      fs_RamdiskWrite
  475.         dd      fs_RamdiskSetFileEnd
  476.         dd      fs_RamdiskGetFileInfo
  477.         dd      fs_RamdiskSetFileInfo
  478.         dd      0
  479.         dd      fs_RamdiskDelete
  480.         dd      fs_RamdiskCreateFolder
  481. fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4
  482.  
  483. fs_OnFloppy:
  484.         cmp     ecx, 2
  485.         ja      file_system_lfn.notfound
  486.         mov     eax, [ebx]
  487.         cmp     eax, fs_NumFloppyServices
  488.         jae     fs_OnRamdisk.not_impl
  489.         call    reserve_flp
  490.         mov     [flp_number], cl
  491.         mov     ecx, [ebx+12]
  492.         mov     edx, [ebx+16]
  493.    ;     add     edx, std_application_base_address
  494.         add     ebx, 4
  495.         call    dword [fs_FloppyServices + eax*4]
  496.         and     [flp_status], 0
  497.         mov     [image_of_eax], eax
  498.         mov     [image_of_ebx], ebx
  499.         ret
  500.  
  501. fs_FloppyServices:
  502.         dd      fs_FloppyRead
  503.         dd      fs_FloppyReadFolder
  504.         dd      fs_FloppyRewrite
  505.         dd      fs_FloppyWrite
  506.         dd      fs_FloppySetFileEnd
  507.         dd      fs_FloppyGetFileInfo
  508.         dd      fs_FloppySetFileInfo
  509.         dd      0
  510.         dd      fs_FloppyDelete
  511.         dd      fs_FloppyCreateFolder
  512. fs_NumFloppyServices = ($ - fs_FloppyServices)/4
  513.  
  514. fs_OnHd0:
  515.         call    reserve_hd1
  516.         mov     [hdbase], 0x1F0
  517.         mov     [hdid], 0
  518.         push    1
  519.         jmp     fs_OnHd
  520. fs_OnHd1:
  521.         call    reserve_hd1
  522.         mov     [hdbase], 0x1F0
  523.         mov     [hdid], 0x10
  524.         push    2
  525.         jmp     fs_OnHd
  526. fs_OnHd2:
  527.         call    reserve_hd1
  528.         mov     [hdbase], 0x170
  529.         mov     [hdid], 0
  530.         push    3
  531.         jmp     fs_OnHd
  532. fs_OnHd3:
  533.         call    reserve_hd1
  534.         mov     [hdbase], 0x170
  535.         mov     [hdid], 0x10
  536.         push    4
  537. fs_OnHd:
  538.         call    reserve_hd_channel
  539.         pop     eax
  540.         mov     [hdpos], eax
  541.         cmp     ecx, 0x100
  542.         jae     fs_OnHdAndBd.nf
  543.         cmp     cl, [DRIVE_DATA+1+eax]
  544. fs_OnHdAndBd:
  545.         jbe     @f
  546. .nf:
  547.         call    free_hd_channel
  548.         and     [hd1_status], 0
  549.         mov     dword [image_of_eax], 5       ; not found
  550.         ret
  551. @@:
  552.         mov     [fat32part], ecx
  553.         push    ebx esi
  554.         call    choice_necessity_partition_1
  555.         pop     esi ebx
  556.         mov     ecx, [ebx+12]
  557.         mov     edx, [ebx+16]
  558.     ;    add     edx, std_application_base_address
  559.         mov     eax, [ebx]
  560.         cmp     eax, fs_NumHdServices
  561.         jae     .not_impl
  562.         add     ebx, 4
  563.         call    dword [fs_HdServices + eax*4]
  564.         call    free_hd_channel
  565.         and     [hd1_status], 0
  566.         mov     [image_of_eax], eax
  567.         mov     [image_of_ebx], ebx
  568.         ret
  569. .not_impl:
  570.         call    free_hd_channel
  571.         and     [hd1_status], 0
  572.         mov     dword [image_of_eax], 2       ; not implemented
  573.         ret
  574.  
  575. fs_HdServices:
  576.         dd      fs_HdRead
  577.         dd      fs_HdReadFolder
  578.         dd      fs_HdRewrite
  579.         dd      fs_HdWrite
  580.         dd      fs_HdSetFileEnd
  581.         dd      fs_HdGetFileInfo
  582.         dd      fs_HdSetFileInfo
  583.         dd      0
  584.         dd      fs_HdDelete
  585.         dd      fs_HdCreateFolder
  586. fs_NumHdServices = ($ - fs_HdServices)/4
  587.  
  588. ;*******************************************************
  589. fs_OnCd0:
  590.         call    reserve_cd
  591.         mov  [ChannelNumber],1
  592.         mov  [DiskNumber],0
  593.         push    6
  594.         push    1
  595.         jmp     fs_OnCd
  596. fs_OnCd1:
  597.         call    reserve_cd
  598.         mov  [ChannelNumber],1
  599.         mov  [DiskNumber],1
  600.         push    4
  601.         push    2
  602.         jmp     fs_OnCd
  603. fs_OnCd2:
  604.         call    reserve_cd
  605.         mov  [ChannelNumber],2
  606.         mov  [DiskNumber],0
  607.         push    2
  608.         push    3
  609.         jmp     fs_OnCd
  610. fs_OnCd3:
  611.         call    reserve_cd
  612.         mov  [ChannelNumber],2
  613.         mov  [DiskNumber],1
  614.         push    0
  615.         push    4
  616. fs_OnCd:
  617.         call    reserve_cd_channel
  618.         pop     eax
  619.         mov     [cdpos], eax
  620.         pop     eax
  621.         cmp     ecx, 0x100
  622.         jae     .nf
  623.         push    ecx ebx
  624.         mov     cl,al
  625.         mov     bl,[DRIVE_DATA+1]
  626.         shr     bl,cl
  627.         test    bl,2
  628.         pop     ebx ecx
  629.  
  630.         jnz     @f
  631. .nf:
  632.         call    free_cd_channel
  633.         and    [cd_status], 0
  634.         mov     dword [image_of_eax], 5       ; not found
  635.         ret
  636. @@:
  637.         mov     ecx, [ebx+12]
  638.         mov     edx, [ebx+16]
  639.     ;    add     edx, std_application_base_address
  640.         mov     eax, [ebx]
  641.         cmp     eax,fs_NumCdServices
  642.         jae      .not_impl
  643.         add     ebx, 4
  644.         call    dword [fs_CdServices + eax*4]
  645.         call    free_cd_channel
  646.         and     [cd_status], 0
  647.         mov     [image_of_eax], eax
  648.         mov     [image_of_ebx], ebx
  649.         ret
  650. .not_impl:
  651.         call    free_cd_channel
  652.         and     [cd_status], 0
  653.         mov     dword [image_of_eax], 2       ; not implemented
  654.         ret
  655.  
  656. fs_CdServices:
  657.         dd      fs_CdRead
  658.         dd      fs_CdReadFolder
  659.         dd      fs_NotImplemented
  660.         dd      fs_NotImplemented
  661.         dd      fs_NotImplemented
  662.         dd      fs_CdGetFileInfo
  663.         dd      fs_NotImplemented
  664.         dd      0
  665.         dd      fs_NotImplemented
  666.         dd      fs_NotImplemented
  667. fs_NumCdServices = ($ - fs_CdServices)/4
  668.  
  669. ;*******************************************************
  670.  
  671. fs_HasRamdisk:
  672.         mov     al, 1   ; we always have ramdisk
  673.         ret
  674.  
  675. fs_HasFloppy:
  676.         cmp     byte [DRIVE_DATA], 0
  677.         setnz   al
  678.         ret
  679.  
  680. fs_HasHd0:
  681.         mov     al, [DRIVE_DATA+1]
  682.         and     al, 11000000b
  683.         cmp     al, 01000000b
  684.         setz    al
  685.         ret
  686. fs_HasHd1:
  687.         mov     al, [DRIVE_DATA+1]
  688.         and     al, 00110000b
  689.         cmp     al, 00010000b
  690.         setz    al
  691.         ret
  692. fs_HasHd2:
  693.         mov     al, [DRIVE_DATA+1]
  694.         and     al, 00001100b
  695.         cmp     al, 00000100b
  696.         setz    al
  697.         ret
  698. fs_HasHd3:
  699.         mov     al, [DRIVE_DATA+1]
  700.         and     al, 00000011b
  701.         cmp     al, 00000001b
  702.         setz    al
  703.         ret
  704.  
  705. ;*******************************************************
  706. fs_HasCd0:
  707.         mov     al, [DRIVE_DATA+1]
  708.         and     al, 11000000b
  709.         cmp     al, 10000000b
  710.         setz    al
  711.         ret
  712. fs_HasCd1:
  713.         mov     al, [DRIVE_DATA+1]
  714.         and     al, 00110000b
  715.         cmp     al, 00100000b
  716.         setz    al
  717.         ret
  718. fs_HasCd2:
  719.         mov     al, [DRIVE_DATA+1]
  720.         and     al, 00001100b
  721.         cmp     al, 00001000b
  722.         setz    al
  723.         ret
  724. fs_HasCd3:
  725.         mov     al, [DRIVE_DATA+1]
  726.         and     al, 00000011b
  727.         cmp     al, 00000010b
  728.         setz    al
  729.         ret
  730. ;*******************************************************
  731.  
  732. ; fs_NextXXX functions:
  733. ; in: eax = partition number, from which start to scan
  734. ; out: CF=1 => no more partitions
  735. ;      CF=0 => eax=next partition number
  736.  
  737. fs_NextRamdisk:
  738. ; we always have /rd/1
  739.         test    eax, eax
  740.         stc
  741.         jnz     @f
  742.         mov     al, 1
  743.         clc
  744. @@:
  745.         ret
  746.  
  747. fs_NextFloppy:
  748. ; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0)
  749.         test    byte [DRIVE_DATA], 0xF0
  750.         jz      .no1
  751.         test    eax, eax
  752.         jnz     .no1
  753.         inc     eax
  754.         ret     ; CF cleared
  755. .no1:
  756.         test    byte [DRIVE_DATA], 0x0F
  757.         jz      .no2
  758.         cmp     al, 2
  759.         jae     .no2
  760.         mov     al, 2
  761.         clc
  762.         ret
  763. .no2:
  764.         stc
  765.         ret
  766.  
  767. ; on hdx, we have partitions from 1 to [0x40002+x]
  768. fs_NextHd0:
  769.         push    0
  770.         jmp     fs_NextHd
  771. fs_NextHd1:
  772.         push    1
  773.         jmp     fs_NextHd
  774. fs_NextHd2:
  775.         push    2
  776.         jmp     fs_NextHd
  777. fs_NextHd3:
  778.         push    3
  779. fs_NextHd:
  780.         pop     ecx
  781.         movzx   ecx, byte [DRIVE_DATA+2+ecx]
  782.         cmp     eax, ecx
  783.         jae     fs_NextFloppy.no2
  784.         inc     eax
  785.         clc
  786.         ret
  787.  
  788. ;*******************************************************
  789. fs_NextCd:
  790. ; we always have /cdX/1
  791.         test    eax, eax
  792.         stc
  793.         jnz     @f
  794.         mov     al, 1
  795.         clc
  796. @@:
  797.         ret
  798. ;*******************************************************
  799.  
  800. ; Additional FS handlers.
  801. ; This handler gets the control each time when fn 70 is called
  802. ; with unknown item of root subdirectory.
  803. ; in: esi -> name
  804. ;     ebp = 0 or rest of name relative to esi
  805. ; out: if the handler processes path, he must not return in file_system_lfn,
  806. ;      but instead pop return address and return directly to the caller
  807. ;      otherwise simply return
  808.  
  809. ; here we test for /bd<N>/... - BIOS disks
  810. biosdisk_handler:
  811.         cmp     [NumBiosDisks], 0
  812.         jz      .ret
  813.         mov     al, [esi]
  814.         or      al, 20h
  815.         cmp     al, 'b'
  816.         jnz     .ret
  817.         mov     al, [esi+1]
  818.         or      al, 20h
  819.         cmp     al, 'd'
  820.         jnz     .ret
  821.         push    esi
  822.         inc     esi
  823.         inc     esi
  824.         cmp     byte [esi], '0'
  825.         jb      .ret2
  826.         cmp     byte [esi], '9'
  827.         ja      .ret2
  828.         xor     edx, edx
  829. @@:
  830.         lodsb
  831.         test    al, al
  832.         jz      .ok
  833.         cmp     al, '/'
  834.         jz      .ok
  835.         sub     al, '0'
  836.         cmp     al, 9
  837.         ja      .ret2
  838.         lea     edx, [edx*5]
  839.         lea     edx, [edx*2+eax]
  840.         jmp     @b
  841. .ret2:
  842.         pop     esi
  843. .ret:
  844.         ret
  845. .ok:
  846.         cmp     al, '/'
  847.         jz      @f
  848.         dec     esi
  849. @@:
  850.         add     dl, 80h
  851.         xor     ecx, ecx
  852. @@:
  853.         cmp     dl, [BiosDisksData+ecx*4]
  854.         jz      .ok2
  855.         inc     ecx
  856.         cmp     ecx, [NumBiosDisks]
  857.         jb      @b
  858.         jmp     .ret2
  859. .ok2:
  860.         add     esp, 8
  861.         test    al, al
  862.         jnz     @f
  863.         mov     esi, fs_BdNext
  864.         jmp     file_system_lfn.maindir_noesi
  865. @@:
  866.         push    ecx
  867.         push    fs_OnBd
  868.         mov     edi, esp
  869.         jmp     file_system_lfn.found2
  870.  
  871. fs_BdNext:
  872.         cmp     eax, [BiosDiskPartitions+ecx*4]
  873.         inc     eax
  874.         cmc
  875.         ret
  876.  
  877. fs_OnBd:
  878.         pop     edx edx
  879. ; edx = disk number, ecx = partition number
  880. ; esi+ebp = name
  881.         call    reserve_hd1
  882.         add     edx, 0x80
  883.         mov     [hdpos], edx
  884.         cmp     ecx, [BiosDiskPartitions+(edx-0x80)*4]
  885.         jmp     fs_OnHdAndBd
  886.  
  887. ; This handler is called when virtual root is enumerated
  888. ; and must return all items which can be handled by this.
  889. ; It is called several times, first time with eax=0
  890. ; in: eax = 0 for first call, previously returned value for subsequent calls
  891. ; out: eax = 0 => no more items
  892. ;      eax != 0 => buffer pointed to by edi contains name of item
  893.  
  894. ; here we enumerate existing BIOS disks /bd<N>
  895. biosdisk_enum_root:
  896.         cmp     eax, [NumBiosDisks]
  897.         jae     .end
  898.         push    eax
  899.         movzx   eax, byte [BiosDisksData+eax*4]
  900.         sub     al, 80h
  901.         push    eax
  902.         mov     al, 'b'
  903.         stosb
  904.         mov     al, 'd'
  905.         stosb
  906.         pop     eax
  907.         cmp     al, 10
  908.         jae     .big
  909.         add     al, '0'
  910.         stosb
  911.         mov     byte [edi], 0
  912.         pop     eax
  913.         inc     eax
  914.         ret
  915. .end:
  916.         xor     eax, eax
  917.         ret
  918. .big:
  919.         push    ecx
  920.         push    -'0'
  921.         mov     ecx, 10
  922. @@:
  923.         xor     edx, edx
  924.         div     ecx
  925.         push    edx
  926.         test    eax, eax
  927.         jnz     @b
  928.         xchg    eax, edx
  929. @@:
  930.         pop     eax
  931.         add     al, '0'
  932.         stosb
  933.         jnz     @b
  934.         pop     ecx
  935.         pop     eax
  936.         inc     eax
  937.         ret
  938.  
  939. process_replace_file_name:
  940.         mov     ebp, [full_file_name_table]
  941.         mov     edi, [full_file_name_table.size]
  942.         dec     edi
  943.         shl     edi, 7
  944.         add     edi, ebp
  945. .loop:
  946.         cmp     edi, ebp
  947.         jb      .notfound
  948.         push    esi edi
  949. @@:
  950.         cmp     byte [edi], 0
  951.         jz      .dest_done
  952.         lodsb
  953.         test    al, al
  954.         jz      .cont
  955.         or      al, 20h
  956.         scasb
  957.         jz      @b
  958.         jmp     .cont
  959. .dest_done:
  960.         cmp     byte [esi], 0
  961.         jz      .found
  962.         cmp     byte [esi], '/'
  963.         jnz     .cont
  964.         inc     esi
  965.         jmp     .found
  966. .cont:
  967.         pop     edi esi
  968.         sub     edi, 128
  969.         jmp     .loop
  970. .found:
  971.         pop     edi eax
  972.         mov     ebp, esi
  973.         cmp     byte [esi], 0
  974.         lea     esi, [edi+64]
  975.         jnz     .ret
  976. .notfound:
  977.         xor     ebp, ebp
  978. .ret:
  979.         ret
  980.  
  981. sys_current_directory:
  982.         mov     esi, [current_slot]
  983.         mov     esi, [esi+APPDATA.cur_dir]
  984.         mov     edx, esi
  985.         dec     eax
  986.         jz      .set
  987.         dec     eax
  988.         jz      .get
  989.         ret
  990. .get:
  991. ; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
  992. ; for our code: ebx->buffer,ecx=len
  993. @@:
  994.         lodsb
  995.         test    al, al
  996.         jnz     @b
  997.         sub     esi, edx
  998.         inc     esi
  999.         mov     [esp+36], esi
  1000.         cmp     ecx, esi
  1001.         jbe     @f
  1002.         mov     ecx, esi
  1003. @@:
  1004.         cmp     ecx, 1
  1005.         jbe     .ret
  1006.         mov     esi, edx
  1007.         mov     edi, ebx
  1008.         mov     al, '/'
  1009.         stosb
  1010.         dec     ecx
  1011.         dec     ecx
  1012.         rep     movsb
  1013.         mov     byte [edi], 0
  1014. .ret:
  1015.         ret
  1016. .set:
  1017. ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
  1018. ; for our code: ebx->string to set
  1019. @@:
  1020.         inc     esi
  1021.         cmp     byte [esi-1], 0
  1022.         jnz     @b
  1023.         dec     esi
  1024.         cmp     byte [ebx], '/'
  1025.         jz      .set_absolute
  1026. ; string gives relative path
  1027. .relative:
  1028.         cmp     byte [ebx], 0
  1029.         jz      .set_ok
  1030.         cmp     word [ebx], '.'
  1031.         jz      .set_ok
  1032.         cmp     word [ebx], './'
  1033.         jnz     @f
  1034.         add     ebx, 2
  1035.         jmp     .relative
  1036. @@:
  1037.         cmp     word [ebx], '..'
  1038.         jnz     .doset_relative
  1039.         cmp     byte [ebx+2], 0
  1040.         jz      @f
  1041.         cmp     byte [ebx+2], '/'
  1042.         jnz     .doset_relative
  1043. @@:
  1044.         dec     esi
  1045.         cmp     byte [esi], '/'
  1046.         jnz     @b
  1047.         mov     byte [esi], 0
  1048.         add     ebx, 3
  1049.         jmp     .relative
  1050. .doset_relative:
  1051.         add     edx, 0x1000
  1052.         mov     byte [esi], '/'
  1053.         inc     esi
  1054.         cmp     esi, edx
  1055.         jae     .overflow_esi
  1056. @@:
  1057.         mov     al, [ebx]
  1058.         inc     ebx
  1059.         mov     [esi], al
  1060.         inc     esi
  1061.         test    al, al
  1062.         jz      .set_ok
  1063.         cmp     esi, edx
  1064.         jb      @b
  1065. .overflow_esi:
  1066.         mov     byte [esi-1], 0         ; force null-terminated string
  1067. .set_ok:
  1068.         ret
  1069. .set_absolute:
  1070.         lea     esi, [ebx+1]
  1071.         call    process_replace_file_name
  1072.         mov     edi, edx
  1073.         add     edx, 0x1000
  1074. .set_copy:
  1075.         lodsb
  1076.         stosb
  1077.         test    al, al
  1078.         jz      .set_part2
  1079. .set_copy_cont:
  1080.         cmp     edi, edx
  1081.         jb      .set_copy
  1082. .overflow_edi:
  1083.         mov     byte [edi-1], 0
  1084.         ret
  1085. .set_part2:
  1086.         mov     esi, ebp
  1087.         xor     ebp, ebp
  1088.         test    esi, esi
  1089.         jz      .set_ok
  1090.         mov     byte [edi-1], '/'
  1091.         jmp     .set_copy_cont
  1092.