Subversion Repositories Kolibri OS

Rev

Rev 1491 | Rev 2119 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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