Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 4273 $
  9.  
  10. ERROR_SUCCESS        = 0
  11. ERROR_DISK_BASE      = 1
  12. ERROR_UNSUPPORTED_FS = 2
  13. ERROR_UNKNOWN_FS     = 3
  14. ERROR_PARTITION      = 4
  15. ERROR_FILE_NOT_FOUND = 5
  16. ERROR_END_OF_FILE    = 6
  17. ERROR_MEMORY_POINTER = 7
  18. ERROR_DISK_FULL      = 8
  19. ERROR_FAT_TABLE      = 9 ;deprecated
  20. ERROR_FS_FAIL        = 9
  21. ERROR_ACCESS_DENIED  = 10
  22. ERROR_DEVICE         = 11
  23.  
  24. image_of_eax EQU esp+32
  25. image_of_ebx EQU esp+20
  26.  
  27. ; System function 70 - files with long names (LFN)
  28. ; diamond, 2006
  29.  
  30. iglobal
  31. ; in this table names must be in lowercase
  32. rootdirs:
  33. ;**********************************************
  34.         db      3,'cd0'
  35.         dd      fs_OnCd0
  36.         dd      fs_NextCd
  37.         db      3,'cd1'
  38.         dd      fs_OnCd1
  39.         dd      fs_NextCd
  40.         db      3,'cd2'
  41.         dd      fs_OnCd2
  42.         dd      fs_NextCd
  43.         db      3,'cd3'
  44.         dd      fs_OnCd3
  45.         dd      fs_NextCd
  46. ;***********************************************
  47.         db      0
  48.  
  49.  
  50. virtual_root_query:
  51. ;**********************************************
  52.         dd      fs_HasCd0
  53.         db      'cd0',0
  54.         dd      fs_HasCd1
  55.         db      'cd1',0
  56.         dd      fs_HasCd2
  57.         db      'cd2',0
  58.         dd      fs_HasCd3
  59.         db      'cd3',0
  60. ;**********************************************
  61.         dd      0
  62.  
  63. fs_additional_handlers:
  64.         dd      dyndisk_handler, dyndisk_enum_root
  65. ; add new handlers here
  66.         dd      0
  67.  
  68. endg
  69.  
  70. file_system_lfn_protected:
  71.         pushad
  72.         call    protect_from_terminate
  73.         call    file_system_lfn
  74.         call    unprotect_from_terminate
  75.         popad
  76.         mov     [image_of_eax], eax
  77.         mov     [image_of_ebx], ebx
  78.         ret
  79.  
  80. file_system_lfn:
  81. ; in: ebx->fileinfo block
  82. ; operation codes:
  83. ; 0 : read file
  84. ; 1 : read folder
  85. ; 2 : create/rewrite file
  86. ; 3 : write/append to file
  87. ; 4 : set end of file
  88. ; 5 : get file/directory attributes structure
  89. ; 6 : set file/directory attributes structure
  90. ; 7 : start application
  91. ; 8 : delete file
  92. ; 9 : create directory
  93.  
  94. ; parse file name
  95.         lea     esi, [ebx+20]
  96.         lodsb
  97.         test    al, al
  98.         jnz     @f
  99.         mov     esi, [esi]
  100.         lodsb
  101. @@:
  102.         cmp     al, '/'
  103.         jz      .notcurdir
  104.         dec     esi
  105.         mov     ebp, esi
  106.         test    al, al
  107.         jnz     @f
  108.         xor     ebp, ebp
  109. @@:
  110.         mov     esi, [current_slot]
  111.         mov     esi, [esi+APPDATA.cur_dir]
  112.         jmp     .parse_normal
  113. .notcurdir:
  114.         cmp     byte [esi], 0
  115.         jz      .rootdir
  116.         call    process_replace_file_name
  117. .parse_normal:
  118.         cmp     dword [ebx], 7
  119.         jne     @F
  120.         mov     edx, [ebx+4]
  121.         mov     ebx, [ebx+8]
  122.         call    fs_execute; esi+ebp, ebx, edx
  123.         mov     [image_of_eax], eax
  124.         ret
  125. @@:
  126.         mov     edi, rootdirs-8
  127.         xor     ecx, ecx
  128.         push    esi
  129. .scan1:
  130.         pop     esi
  131.         add     edi, ecx
  132.         scasd
  133.         scasd
  134.         mov     cl, byte [edi]
  135.         test    cl, cl
  136.         jz      .notfound_try
  137.         inc     edi
  138.         push    esi
  139. @@:
  140.         lodsb
  141.         or      al, 20h
  142.         scasb
  143.         loopz   @b
  144.         jnz     .scan1
  145.         lodsb
  146.         cmp     al, '/'
  147.         jz      .found1
  148.         test    al, al
  149.         jnz     .scan1
  150.         pop     eax
  151. ; directory /xxx
  152. .maindir:
  153.         mov     esi, [edi+4]
  154. .maindir_noesi:
  155.         cmp     dword [ebx], 1
  156.         jnz     .access_denied
  157.         xor     eax, eax
  158.         mov     ebp, [ebx+12]                   ;количество блоков для считывания
  159.         mov     edx, [ebx+16]                   ;куда записывать рузельтат
  160.     ;    add     edx, std_application_base_address
  161.         push    dword [ebx+4]   ; first block
  162.         mov     ebx, [ebx+8]    ; flags
  163. ; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler
  164.         mov     edi, edx
  165.         push    ecx
  166.         mov     ecx, 32/4
  167.         rep stosd
  168.         pop     ecx
  169.         mov     byte [edx], 1   ; version
  170. .maindir_loop:
  171.         call    esi
  172.         jc      .maindir_done
  173.         inc     dword [edx+8]
  174.         dec     dword [esp]
  175.         jns     .maindir_loop
  176.         dec     ebp
  177.         js      .maindir_loop
  178.         inc     dword [edx+4]
  179.         mov     dword [edi], 0x10       ; attributes: folder
  180.         mov     dword [edi+4], 1        ; name type: UNICODE
  181.         push    eax
  182.         xor     eax, eax
  183.         add     edi, 8
  184.         push    ecx
  185.         mov     ecx, 40/4-2
  186.         rep stosd
  187.         pop     ecx
  188.         pop     eax
  189.         push    eax edx
  190. ; convert number in eax to decimal UNICODE string
  191.         push    edi
  192.         push    ecx
  193.         push    -'0'
  194.         mov     ecx, 10
  195. @@:
  196.         xor     edx, edx
  197.         div     ecx
  198.         push    edx
  199.         test    eax, eax
  200.         jnz     @b
  201. @@:
  202.         pop     eax
  203.         add     al, '0'
  204.         stosb
  205.         test    bl, 1           ; UNICODE name?
  206.         jz      .ansi2
  207.         mov     byte [edi], 0
  208.         inc     edi
  209. .ansi2:
  210.         test    al, al
  211.         jnz     @b
  212.         mov     byte [edi-1], 0
  213.         pop     ecx
  214.         pop     edi
  215. ; UNICODE name length is 520 bytes, ANSI - 264
  216.         add     edi, 520
  217.         test    bl, 1
  218.         jnz     @f
  219.         sub     edi, 520-264
  220. @@:
  221.         pop     edx eax
  222.         jmp     .maindir_loop
  223. .maindir_done:
  224.         pop     eax
  225.         mov     ebx, [edx+4]
  226.         xor     eax, eax
  227.         dec     ebp
  228.         js      @f
  229.         mov     al, ERROR_END_OF_FILE
  230. @@:
  231.         mov     [image_of_eax], eax
  232.         mov     [image_of_ebx], ebx
  233.         ret
  234. ; directory /
  235. .rootdir:
  236.         cmp     dword [ebx], 1  ; read folder?
  237.         jz      .readroot
  238. .access_denied:
  239.         mov     dword [image_of_eax], 10      ; access denied
  240.         ret
  241.  
  242. .readroot:
  243. ; virtual root folder - special handler
  244.         mov     esi, virtual_root_query
  245.         mov     ebp, [ebx+12]
  246.         mov     edx, [ebx+16]
  247.     ;    add     edx, std_application_base_address
  248.         push    dword [ebx+4]   ; first block
  249.         mov     ebx, [ebx+8]    ; flags
  250.         xor     eax, eax
  251. ; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area
  252.         mov     edi, edx
  253.         mov     ecx, 32/4
  254.         rep stosd
  255.         mov     byte [edx], 1   ; version
  256. .readroot_loop:
  257.         cmp     dword [esi], eax
  258.         jz      .readroot_done_static
  259.         call    dword [esi]
  260.         add     esi, 4
  261.         test    eax, eax
  262.         jnz     @f
  263. .readroot_next:
  264.         or      ecx, -1
  265.         xchg    esi, edi
  266.         repnz scasb
  267.         xchg    esi, edi
  268.         jmp     .readroot_loop
  269. @@:
  270.         xor     eax, eax
  271.         inc     dword [edx+8]
  272.         dec     dword [esp]
  273.         jns     .readroot_next
  274.         dec     ebp
  275.         js      .readroot_next
  276.         inc     dword [edx+4]
  277.         mov     dword [edi], 0x10       ; attributes: folder
  278.         mov     dword [edi+4], ebx      ; name type: UNICODE
  279.         add     edi, 8
  280.         mov     ecx, 40/4-2
  281.         rep stosd
  282.         push    edi
  283. @@:
  284.         lodsb
  285.         stosb
  286.         test    bl, 1
  287.         jz      .ansi
  288.         mov     byte [edi], 0
  289.         inc     edi
  290. .ansi:
  291.         test    eax, eax
  292.         jnz     @b
  293.         pop     edi
  294.         add     edi, 520
  295.         test    bl, 1
  296.         jnz     .readroot_loop
  297.         sub     edi, 520-264
  298.         jmp     .readroot_loop
  299. .readroot_done_static:
  300.         mov     esi, fs_additional_handlers-8
  301.         sub     esp, 16
  302. .readroot_ah_loop:
  303.         add     esi, 8
  304.         cmp     dword [esi], 0
  305.         jz      .readroot_done
  306.         xor     eax, eax
  307. .readroot_ah_loop2:
  308.         push    edi
  309.         lea     edi, [esp+4]
  310.         call    dword [esi+4]
  311.         pop     edi
  312.         test    eax, eax
  313.         jz      .readroot_ah_loop
  314.         inc     dword [edx+8]
  315.         dec     dword [esp+16]
  316.         jns     .readroot_ah_loop2
  317.         dec     ebp
  318.         js      .readroot_ah_loop2
  319.         push    eax
  320.         xor     eax, eax
  321.         inc     dword [edx+4]
  322.         mov     dword [edi], 0x10       ; attributes: folder
  323.         mov     dword [edi+4], ebx
  324.         add     edi, 8
  325.         mov     ecx, 40/4-2
  326.         rep stosd
  327.         push    esi edi
  328.         lea     esi, [esp+12]
  329. @@:
  330.         lodsb
  331.         stosb
  332.         test    bl, 1
  333.         jz      .ansi3
  334.         mov     byte [edi], 0
  335.         inc     edi
  336. .ansi3:
  337.         test    al, al
  338.         jnz     @b
  339.         pop     edi esi eax
  340.         add     edi, 520
  341.         test    bl, 1
  342.         jnz     .readroot_ah_loop2
  343.         sub     edi, 520-264
  344.         jmp     .readroot_ah_loop2
  345. .readroot_done:
  346.         add     esp, 16
  347.         pop     eax
  348.         mov     ebx, [edx+4]
  349.         xor     eax, eax
  350.         dec     ebp
  351.         js      @f
  352.         mov     al, ERROR_END_OF_FILE
  353. @@:
  354.         mov     [image_of_eax], eax
  355.         mov     [image_of_ebx], ebx
  356.         ret
  357. .notfound_try:
  358.         mov     edi, fs_additional_handlers
  359. @@:
  360.         cmp     dword [edi], 0
  361.         jz      .notfound
  362.         call    dword [edi]
  363.         scasd
  364.         scasd
  365.         jmp     @b
  366. .notfound:
  367.         mov     dword [image_of_eax], ERROR_FILE_NOT_FOUND
  368.         and     dword [image_of_ebx], 0
  369.         ret
  370.  
  371. .notfounda:
  372.         cmp     edi, esp
  373.         jnz     .notfound
  374.         call    dword [edi+4]
  375.         add     esp, 16
  376.         jmp     .notfound
  377.  
  378. .found1:
  379.         pop     eax
  380.         cmp     byte [esi], 0
  381.         jz      .maindir
  382. .found2:
  383. ; read partition number
  384.         xor     ecx, ecx
  385.         xor     eax, eax
  386. @@:
  387.         lodsb
  388.         cmp     al, '/'
  389.         jz      .done1
  390.         test    al, al
  391.         jz      .done1
  392.         sub     al, '0'
  393.         cmp     al, 9
  394.         ja      .notfounda
  395.         lea     ecx, [ecx*5]
  396.         lea     ecx, [ecx*2+eax]
  397.         jmp     @b
  398. .done1:
  399.         jecxz   .notfounda
  400.         test    al, al
  401.         jnz     @f
  402.         dec     esi
  403. @@:
  404.         cmp     byte [esi], 0
  405.         jnz     @f
  406.         test    ebp, ebp
  407.         jz      @f
  408.         mov     esi, ebp
  409.         xor     ebp, ebp
  410. @@:
  411. ; now [edi] contains handler address, ecx - partition number,
  412. ; esi points to ASCIIZ string - rest of name
  413.         jmp     dword [edi]
  414.  
  415. ; handlers for devices
  416. ; in: ecx = 0 => query virtual directory /xxx
  417. ; in: ecx = partition number
  418. ;     esi -> relative (for device) name
  419. ;     ebx -> fileinfo
  420. ;     ebp = 0 or pointer to rest of name from folder addressed by esi
  421. ; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
  422.  
  423. fs_NotImplemented:
  424.         mov     eax, 2
  425.         ret
  426.  
  427. ;*******************************************************
  428. fs_OnCd0:
  429.         call    reserve_cd
  430.         mov     [ChannelNumber], 1
  431.         mov     [DiskNumber], 0
  432.         push    6
  433.         push    1
  434.         jmp     fs_OnCd
  435. fs_OnCd1:
  436.         call    reserve_cd
  437.         mov     [ChannelNumber], 1
  438.         mov     [DiskNumber], 1
  439.         push    4
  440.         push    2
  441.         jmp     fs_OnCd
  442. fs_OnCd2:
  443.         call    reserve_cd
  444.         mov     [ChannelNumber], 2
  445.         mov     [DiskNumber], 0
  446.         push    2
  447.         push    3
  448.         jmp     fs_OnCd
  449. fs_OnCd3:
  450.         call    reserve_cd
  451.         mov     [ChannelNumber], 2
  452.         mov     [DiskNumber], 1
  453.         push    0
  454.         push    4
  455. fs_OnCd:
  456.         call    reserve_cd_channel
  457.         pop     eax
  458.         mov     [cdpos], eax
  459.         pop     eax
  460.         cmp     ecx, 0x100
  461.         jae     .nf
  462.         push    ecx ebx
  463.         mov     cl, al
  464.         mov     bl, [DRIVE_DATA+1]
  465.         shr     bl, cl
  466.         test    bl, 2
  467.         pop     ebx ecx
  468.  
  469.         jnz     @f
  470. .nf:
  471.         call    free_cd_channel
  472.         and     [cd_status], 0
  473.         mov     dword [image_of_eax], 5       ; not found
  474.         ret
  475. @@:
  476.         mov     ecx, [ebx+12]
  477.         mov     edx, [ebx+16]
  478.     ;    add     edx, std_application_base_address
  479.         mov     eax, [ebx]
  480.         cmp     eax, fs_NumCdServices
  481.         jae     .not_impl
  482.         add     ebx, 4
  483.         call    dword [fs_CdServices + eax*4]
  484.         call    free_cd_channel
  485.         and     [cd_status], 0
  486.         mov     [image_of_eax], eax
  487.         mov     [image_of_ebx], ebx
  488.         ret
  489. .not_impl:
  490.         call    free_cd_channel
  491.         and     [cd_status], 0
  492.         mov     dword [image_of_eax], 2       ; not implemented
  493.         ret
  494.  
  495. fs_CdServices:
  496.         dd      fs_CdRead
  497.         dd      fs_CdReadFolder
  498.         dd      fs_NotImplemented
  499.         dd      fs_NotImplemented
  500.         dd      fs_NotImplemented
  501.         dd      fs_CdGetFileInfo
  502.         dd      fs_NotImplemented
  503.         dd      0
  504.         dd      fs_NotImplemented
  505.         dd      fs_NotImplemented
  506. fs_NumCdServices = ($ - fs_CdServices)/4
  507.  
  508. ;*******************************************************
  509. fs_HasCd0:
  510.         test    byte [DRIVE_DATA+1], 10000000b
  511.         setnz   al
  512.         ret
  513. fs_HasCd1:
  514.         test    byte [DRIVE_DATA+1], 00100000b
  515.         setnz   al
  516.         ret
  517. fs_HasCd2:
  518.         test    byte [DRIVE_DATA+1], 00001000b
  519.         setnz   al
  520.         ret
  521. fs_HasCd3:
  522.         test    byte [DRIVE_DATA+1], 00000010b
  523.         setnz   al
  524.         ret
  525. ;*******************************************************
  526.  
  527. ; fs_NextXXX functions:
  528. ; in: eax = partition number, from which start to scan
  529. ; out: CF=1 => no more partitions
  530. ;      CF=0 => eax=next partition number
  531.  
  532. ;*******************************************************
  533. fs_NextCd:
  534. ; we always have /cdX/1
  535.         test    eax, eax
  536.         stc
  537.         jnz     @f
  538.         mov     al, 1
  539.         clc
  540. @@:
  541.         ret
  542. ;*******************************************************
  543.  
  544. ;-----------------------------------------------------------------------------
  545. process_replace_file_name:
  546. ; in
  547. ; esi - path with filename(f.70)
  548. ;
  549. ; out
  550. ; ebp - full filename
  551.         pushfd
  552.         cli
  553.         mov     ebp, [full_file_name_table]
  554.         xor     edi, edi
  555. .loop:
  556.         cmp     edi, [full_file_name_table.size]
  557.         jae     .notfound
  558.         push    esi edi
  559.         shl     edi, 7 ; edi*128
  560.         add     edi, ebp
  561. @@:
  562.         cmp     byte [edi], 0 ; end of dir_name
  563.         jz      .dest_done
  564.         lodsb
  565.         test    al, al
  566.         jz      .cont
  567.         or      al, 20h ; 32 - space char
  568.         scasb
  569.         jz      @b
  570.         jmp     .cont
  571. .dest_done:
  572.         cmp     byte [esi], 0
  573.         jz      .found
  574.         cmp     byte [esi], '/'
  575.         jnz     .cont
  576.         inc     esi
  577.         jmp     .found
  578. .cont:
  579.         pop     edi esi
  580.         inc     edi
  581.         jmp     .loop
  582. .found:
  583.         pop     edi eax
  584.         shl     edi, 7 ; edi*128
  585.         add     edi, ebp
  586.         mov     ebp, esi
  587.         cmp     byte [esi], 0
  588.         lea     esi, [edi+64]
  589.         jnz     .ret
  590. .notfound:
  591.         xor     ebp, ebp
  592. .ret:
  593.         popfd
  594.         ret
  595. ;-----------------------------------------------------------------------------
  596. uglobal
  597. lock_flag_for_f30_3 rb 1
  598. endg
  599.        
  600. sys_current_directory:
  601. ;       mov     esi, [current_slot]
  602. ;       mov     esi, [esi+APPDATA.cur_dir]
  603. ;       mov     edx, esi
  604.  
  605. ;get length string of appdata.cur_dir
  606.         mov     eax, [current_slot]
  607.         mov     edi, [eax+APPDATA.cur_dir]
  608.  
  609.         dec     ebx
  610.         jz      .set
  611.         dec     ebx
  612.         jz      .get
  613.         dec     ebx
  614.         jz      .mount_additional_directory
  615.         ret
  616.  
  617. .mount_additional_directory:
  618. ; sysfunction 30.2: [for app] eax=30,ebx=3,ecx->dir name+dir path (128)
  619. ; for our code: nothing
  620.  
  621. ; check lock of the function
  622.         cmp     [lock_flag_for_f30_3], 1
  623.         je      @f
  624.        
  625.         mov     esi, ecx
  626.         mov     edi, sysdir_name1
  627. ; copying fake directory name
  628.         mov     ecx, 63
  629.         pushfd
  630.         cli
  631.         cld
  632.         rep movsb
  633. ; terminator of name, in case if we get the inlet trash
  634.         inc     esi
  635.         xor     eax, eax
  636.         stosb
  637. ; copying real directory path for mounting
  638.         mov     ecx, 63
  639.         rep movsb
  640. ; terminator of name, in case if we get the inlet trash
  641.         xor     eax, eax
  642.         stosb
  643. ; increase the pointer of inputs for procedure "process_replace_file_name"        
  644.         mov     [full_file_name_table.size], 2
  645. ; block the ability to call f.30.3 because for one session is necessary
  646. ; for us only once
  647.         mov     [lock_flag_for_f30_3], 1
  648.         popfd
  649. @@:
  650.         ret
  651.        
  652. .get:
  653. ; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
  654. ; for our code: ebx->buffer,ecx=len
  655. max_cur_dir     equ     0x1000
  656.  
  657.         mov     ebx, edi
  658.  
  659.         push    ecx
  660.         push    edi
  661.  
  662.         xor     eax, eax
  663.         mov     ecx, max_cur_dir
  664.  
  665.         repne scasb             ;find zerro at and string
  666.         jnz     .error          ; no zero in cur_dir: internal error, should not happen
  667.  
  668.         sub     edi, ebx        ;lenght for copy
  669.         inc     edi
  670.         mov     [esp+32+8], edi ;return in eax
  671.  
  672.         cmp     edx, edi
  673.         jbe     @f
  674.         mov     edx, edi
  675. @@:
  676. ;source string
  677.         pop     esi
  678. ;destination string
  679.         pop     edi
  680.         cmp     edx, 1
  681.         jbe     .ret
  682.  
  683.         mov     al, '/'         ;start string with '/'
  684.         stosb
  685.         mov     ecx, edx
  686.         rep movsb               ;copy string
  687. .ret:
  688.         ret
  689.  
  690. .error:
  691.         add     esp, 8
  692.         or      dword [esp+32], -1      ;error not found zerro at string ->[eax+APPDATA.cur_dir]
  693.         ret
  694. .set:
  695. ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
  696. ; for our code: ebx->string to set
  697. ; use generic resolver with APPDATA.cur_dir as destination
  698.         push    max_cur_dir     ;0x1000
  699.         push    edi     ;destination
  700.         mov     ebx, ecx
  701.         call    get_full_file_name
  702.         ret
  703.  
  704. ; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination
  705. ; destroys all registers except ebp,esp
  706. get_full_file_name:
  707.         push    ebp
  708.         mov     esi, [current_slot]
  709.         mov     esi, [esi+APPDATA.cur_dir]
  710.         mov     edx, esi
  711. @@:
  712.         inc     esi
  713.         cmp     byte [esi-1], 0
  714.         jnz     @b
  715.         dec     esi
  716.         cmp     byte [ebx], '/'
  717.         jz      .set_absolute
  718. ; string gives relative path
  719.         mov     edi, [esp+8]    ; destination
  720. .relative:
  721.         cmp     byte [ebx], 0
  722.         jz      .set_ok
  723.         cmp     word [ebx], '.'
  724.         jz      .set_ok
  725.         cmp     word [ebx], './'
  726.         jnz     @f
  727.         add     ebx, 2
  728.         jmp     .relative
  729. @@:
  730.         cmp     word [ebx], '..'
  731.         jnz     .doset_relative
  732.         cmp     byte [ebx+2], 0
  733.         jz      @f
  734.         cmp     byte [ebx+2], '/'
  735.         jnz     .doset_relative
  736. @@:
  737.         dec     esi
  738.         cmp     byte [esi], '/'
  739.         jnz     @b
  740.         add     ebx, 3
  741.         jmp     .relative
  742. .set_ok:
  743.         cmp     edx, edi        ; is destination equal to APPDATA.cur_dir?
  744.         jz      .set_ok.cur_dir
  745.         sub     esi, edx
  746.         cmp     esi, [esp+12]
  747.         jb      .set_ok.copy
  748. .fail:
  749.         mov     byte [edi], 0
  750.         xor     eax, eax        ; fail
  751.         pop     ebp
  752.         ret     8
  753. .set_ok.copy:
  754.         mov     ecx, esi
  755.         mov     esi, edx
  756.         rep movsb
  757.         mov     byte [edi], 0
  758. .ret.ok:
  759.         mov     al, 1   ; ok
  760.         pop     ebp
  761.         ret     8
  762. .set_ok.cur_dir:
  763.         mov     byte [esi], 0
  764.         jmp     .ret.ok
  765. .doset_relative:
  766.         cmp     edx, edi
  767.         jz      .doset_relative.cur_dir
  768.         sub     esi, edx
  769.         cmp     esi, [esp+12]
  770.         jae     .fail
  771.         mov     ecx, esi
  772.         mov     esi, edx
  773.         mov     edx, edi
  774.         rep movsb
  775.         jmp     .doset_relative.copy
  776. .doset_relative.cur_dir:
  777.         mov     edi, esi
  778. .doset_relative.copy:
  779.         add     edx, [esp+12]
  780.         mov     byte [edi], '/'
  781.         inc     edi
  782.         cmp     edi, edx
  783.         jae     .overflow
  784. @@:
  785.         mov     al, [ebx]
  786.         inc     ebx
  787.         stosb
  788.         test    al, al
  789.         jz      .ret.ok
  790.         cmp     edi, edx
  791.         jb      @b
  792. .overflow:
  793.         dec     edi
  794.         jmp     .fail
  795. .set_absolute:
  796.         lea     esi, [ebx+1]
  797.         call    process_replace_file_name
  798.         mov     edi, [esp+8]
  799.         mov     edx, [esp+12]
  800.         add     edx, edi
  801. .set_copy:
  802.         lodsb
  803.         stosb
  804.         test    al, al
  805.         jz      .set_part2
  806. .set_copy_cont:
  807.         cmp     edi, edx
  808.         jb      .set_copy
  809.         jmp     .overflow
  810. .set_part2:
  811.         mov     esi, ebp
  812.         xor     ebp, ebp
  813.         test    esi, esi
  814.         jz      .ret.ok
  815.         mov     byte [edi-1], '/'
  816.         jmp     .set_copy_cont
  817.