------------------------------------------------------------
                        [BUG/PRB.] VFP 9.0 FIX - RATC() FUNCTION
                                January 2024
                 ------------------------------------------------------------
                                     CCB



1. BUG:

     In vfp9 (and vfp6, vfp7, vfp8), sometimes vfp will crash when calling the RATC() function.

     The bug only occurs in DBCS (Double-Byte Character Sets) environments.

     In non-DBCS (Double-Byte Character Sets) environments, the RATC() function is the same as the RAT() function, so there is no the bug.

     There is a test program:

     *PROC testratcfunction

     ?RAT(CHR(0),"12345678") && Displays 0
     ?RATC(CHR(0),"12345678") && Displays 2
     WAIT

     RETURN

     * END OF PROC TESTRATCFUNCTION.

     We think they will display 0, but:
     ?RATC(CHR(0),"12345678") && Displays 2


2. CAUSE:

     When VFP 9.0 and earlier versions calculate RATC(CHR(0),"12345678"),
     please refer to the memory dump data:
     011887C0  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
     011887D0  05 00 09 00 B5 07 18 01 08 00 00 00 10 00 00 00
     011887E0  31 32 33 34 35 36 37 38 AB AB AB AB AB AB AB AB
     011887F0  ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??

     It will search the string CHR(0) from right to left:
     011887E7: 38 ;; it is not equal to CHR(0), search continue...
     011887E6: 37 ;; it is not equal to CHR(0), search continue...
     011887E5: 36 ;; it is not equal to CHR(0), search continue...
     011887E4: 35 ;; it is not equal to CHR(0), search continue...
     011887E3: 34 ;; it is not equal to CHR(0), search continue...
     011887E2: 33 ;; it is not equal to CHR(0), search continue...
     011887E1: 32 ;; it is not equal to CHR(0), search continue...
     011887E0: 31 ;; it is not equal to CHR(0), search continue...
     011887DF: 00 ;; it is equal to CHR(0), search end, but it's wrong!
     In this case, RATC(CHR(0),"12345678") returns a wrong value.

     In some cases, for example, to calculate RATC(CHR(255),"12345678"),
     011887E7: 38 ;; it is not equal to CHR(255), search continue...
     011887E6: 37 ;; it is not equal to CHR(255), search continue...
     011887E5: 36 ;; it is not equal to CHR(255), search continue...
     011887E4: 35 ;; it is not equal to CHR(255), search continue...
     011887E3: 34 ;; it is not equal to CHR(255), search continue...
     011887E2: 33 ;; it is not equal to CHR(255), search continue...
     011887E1: 32 ;; it is not equal to CHR(255), search continue...
     011887E0: 31 ;; it is not equal to CHR(255), search continue...
     011887DF: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887DE: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887DD: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887DC: 10 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887DB: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887DA: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D9: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D8: 08 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D7: 01 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D6: 18 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D5: 07 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D4: B5 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D3: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D2: 09 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D1: 00 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887D0: 05 ;; it is not equal to CHR(255), search continue, but it's wrong!
     011887CF: ?? ;; search in inaccessible memory, the memory access violation exception (exception code 0xC0000005)!
     and then vfp will crash.


3. RESOLUTION:

     We can write some code to fix the BUG.

     Label590b51 ::
             push ebp                                                        ;0x00590b51 :        55
             push edi                                                        ;0x00590b52 :        57
             call  CharPrevA                                   ;0x00590b53 :        ff15f8729100
             movzx edx ,byte ptr [eax]                                       ;0x00590b59 :        0fb610
             test  byte ptr [ edx + offset Data937120 ] , 01h                         ;0x00590b5c :        f6822071930001
             je Label590b71                                                  ;0x00590b63 :        740c
             mov ecx , ebp                                                   ;0x00590b65 :        8bcd
             sub ecx , eax                                                   ;0x00590b67 :        2bc8
             cmp ecx , 01h                                                   ;0x00590b69 :        83f901
             jne Label590b71                                                 ;0x00590b6c :        7503
             dec esi                                                         ;0x00590b6e :        4e
             mov ebp , eax                                                   ;0x00590b6f :        8be8

     Label590b71 ::
             cmp  esi , dword ptr [ esp + 20 ]                               ;0x00590b71 :        3b742414
             mov  dword ptr [ esp + 52 ] , esi                               ;0x00590b75 :        89742434
             mov ebx , esi                                                   ;0x00590b79 :        8bde
             ja Label5435d1                                                  ;0x00590b7b :        0f87502afbff

     Label590b81 ::
             mov  dl , byte ptr [ esp + 19 ]                                 ;0x00590b81 :        8a542413
             cmp  byte ptr [ ebp + 0 ] , dl                                  ;0x00590b85 :        385500
             jne Label590ba4                                                 ;0x00590b88 :        751a
             mov  ecx , dword ptr [ esp + 24 ]                               ;0x00590b8a :        8b4c2418
             mov  esi , dword ptr [ esp + 28 ]                               ;0x00590b8e :        8b74241c
             mov edi , ebp                                                   ;0x00590b92 :        8bfd
             xor eax , eax                                                   ;0x00590b94 :        33c0
             repz cmpsb                                                      ;0x00590b96 :        f3a6
             jne Label590ba0                                                 ;0x00590b98 :        7506
             dec  dword ptr [ esp + 48 ]                                     ;0x00590b9a :        ff4c2430
             je Label590b25                                                  ;0x00590b9e :        7485

     Label590ba0 ::
             mov  edi , dword ptr [ esp + 36 ]                               ;0x00590ba0 :        8b7c2424

     Label590ba4 ::
             push ebp                                                        ;0x00590ba4 :        55
             push edi                                                        ;0x00590ba5 :        57
             call  CharPrevA                                   ;0x00590ba6 :        ff15f8729100
             cmp eax , ebp                                                   ;0x00590bac :        3bc5
             jne Label590bb4                                                 ;0x00590bae :        7504
             inc ebx                                                         ;0x00590bb0 :        43
             dec ebp                                                         ;0x00590bb1 :        4d
             jmp Label590bbc                                                 ;0x00590bb2 :        eb08

     Label590bb4 ::
             mov ecx , eax                                                   ;0x00590bb4 :        8bc8
             sub ecx , ebp                                                   ;0x00590bb6 :        2bcd
             add ebx , ecx                                                   ;0x00590bb8 :        03d9
             mov ebp , eax                                                   ;0x00590bba :        8be8

     Label590bbc ::


     ;
     ;                 -------------------------------------------------
     ;                        VFP 9.0 FIX - RATC() FUNCTION
     ;                                  March 2020
     ;                 -------------------------------------------------
     ;                                     CCB
     ;
     ; Sometimes vfp will crash when calling the RATC() function.
     ;
     ; 2020/3/1, by ccb
     ;

             cmp dword ptr [ esp + 28h ] , offset Label4dae9a ;; Fun4dae39 .. ; proc near
             jne Label590bbd
             cmp dword ptr [ esp + 28h + (4+14h+1Ch) ] , offset Label4a7469 ;; Label4a7459 ..
             jne Label590bbd
             cmp ebp , edi
             jb Label590bcd


     Label590bbd ::
             mov  ecx , dword ptr [ esp + 52 ]                               ;0x00590bbc :        8b4c2434
             mov  eax , dword ptr [ esp + 20 ]                               ;0x00590bc0 :        8b442414
             dec ecx                                                         ;0x00590bc4 :        49
             cmp ebx , eax                                                   ;0x00590bc5 :        3bd8
             mov  dword ptr [ esp + 52 ] , ecx                               ;0x00590bc7 :        894c2434
             jbe Label590b81                                                 ;0x00590bcb :        76b4

     Label590bcd ::
             pop ebp                                                         ;0x00590bcd :        5d
             pop esi                                                         ;0x00590bce :        5e
             pop edi                                                         ;0x00590bcf :        5f
             xor eax , eax                                                   ;0x00590bd0 :        33c0
             pop ebx                                                         ;0x00590bd2 :        5b
             add esp , 018h                                                  ;0x00590bd3 :        83c418
             ret 014h                                                        ;0x00590bd6 :        c21400


4. APPLIES TO:

     VFP 6.0.8167.0
     VFP 6.0.8961.0 (SP5)

     VFP 7.0.0.9262
     VFP 7.0.0.9465 (SP1)

     VFP 8.0.0.2521
     VFP 8.0.0.3117 (SP1)

     VFP 9.0.0.2412
     VFP 9.0.0.3504 (SP1)
     VFP 9.0.0.4611 (SP2)
     VFP 9.0.0.5015 (SP2)
     VFP 9.0.0.5411 (SP2)
     VFP 9.0.0.5721 (SP2)
     VFP 9.0.0.5815 (SP2)
     VFP 9.0.0.6303 (SP2)
     VFP 9.0.0.6602 (SP2)
     VFP 9.0.0.7423 (SP2)

     The bug has been fixed in VFP Advanced.

     IMPORTANT NOTE:
     Some vfp tools (for example, the "Code References" tool) use the RATC() function, sometimes vfp will crash when using these vfp tools.
     Please refer the following files:
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Ffc\_controls.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Ffc\_dataquery.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Ffc\_movers.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Gallery\vfpglry.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Toolbox\_toolbox.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Wizards\apphook.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Samples\Classes\samples.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Samples\Solution\Forms\qbe.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Samples\Solution\Forms\qbf.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Samples\Servers\Foxisapi\Foxis\isapi.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\Tools\xsource\VFPSource\beautify\beautify.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\foxref\foxmatch.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\foxref\foxrefengine.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\toolbox\_toolbox.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\toolbox\_toolboxdefault.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\builders\builders\builder.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wzapp\wzapp.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wzapp\wzapp.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wzcommon\wzengine.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wzcommon\wizmover.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wzquery\emit.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wzquery\wzquery.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wztable\wztbleng.prg
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wztable\wzdbc.vcx
     C:\Program Files (x86)\Microsoft Visual FoxPro 9\tools\xsource\vfpsource\wizards\wztable\wztable.vcx


5. REFERENCE WEBSITES:

     1, baiyujia.com:
     http://www.baiyujia.com

     2, microsoft.com:
     https://social.msdn.microsoft.com/forums/en-US/219a9eb1-f8e5-4c1e-b979-cd127d1a9819/vfp-9-tool-core-references-problem

     3, mzvfp.com:
     http://www.mzvfp.com/read.php?tid=104658
     http://www.mzvfp.com/read.php?tid=104863

     4, csdn.net:
     https://bbs.csdn.net/topics/250084102


6. OTHER:

     For reference only, there is no guarantees.

     Any questions or suggestions, please send me an email at ccb2000@163.com.