-------------------------------------------------
                        VFP 9.0 FIX - INVISIBLE BREAKPOINT
                                 January 2017
                 -------------------------------------------------
                                     CCB



1. BUG:

     Sometimes, vfp debugger stops at some invisible breakpoints.

     There is a test program from Mr. Leonid Lepin (or Mr. meligo):

     *PROC testbreakpoint

     SET STEP OFF
     SET ECHO OFF
     SET DEBUG OFF
     SET ESCAPE OFF
     SET TALK OFF
     SET SAFETY OFF

     _SCREEN.VISIBLE=.T.
     _SCREEN.WINDOWSTATE=2

     ? 'Phantom BreakPoint'
     INSERT INTO tttt (f0,f1,f2,f3,f4,f5) VALUES (CHRTRAN(somestring,'\','/'),1,2,3,4,5)

     RETURN

     * END OF PROC TESTBREAKPOINT.

     We can set a breakpoint at the line:
     INSERT INTO tttt (f0,f1,f2,f3,f4,f5) VALUES (CHRTRAN(somestring,'\','/'),1,2,3,4,5)

     But when we run the program, the debugger stops at the line:
     ? 'Phantom BreakPoint'


2. CAUSE:

     Please refer to the head of the testbreakpoint.fxp:

     00000000:  FE F2 FF 20-02 01 00 00-00 D3 01 00-00 6E 01 00  ................
     00000010:  00 65 00 00-00 00 00 00-00 00 00 00-00 00 00 00  ................
     00000020:  00 00 00 00-00 00 00 DB-85 00 00 00-00 25 00 00  ................
     00000030:  00 00 00 00-00 00 00 00-00 35 01 00-00 0C 00 00  ................
     00000040:  00 1D 01 00-00 00 00 A5-40 33 00 00-00 85 BA 00  ................
     00000050:  06 00 47 31-1F FE 06 00-47 13 1F FE-06 00 47 0C  ................
     00000060:  1F FE 06 00-47 15 1F FE-06 00 47 32-1F FE 06 00  ................
     00000070:  47 2E 1F FE-0D 00 54 E1-39 F7 00 00-10 FC 61 FD  ................
     00000080:  FE 0F 00 54-E1 39 F7 01-00 10 FC F8-01 02 FD FE  ................
     00000090:  1E 00 02 F8-03 01 FC FB-12 00 50 68-61 6E 74 6F  ..........Phanto
     000000A0:  6D 20 42 72-65 61 6B 50-6F 69 6E 74-FD FE 55 00  m BreakPoint....
     000000B0:  72 BC FB 04-00 74 74 74-74 02 F7 02-00 07 F7 03  .......tttt.....
     000000C0:  00 07 F7 04-00 07 F7 05-00 07 F7 06-00 07 F7 07  ................
     000000D0:  00 03 C5 02-FC 43 F7 08-00 FB 01 00-5C FB 01 00  ................
     000000E0:  2F 9D FD 07-FC F8 01 01-FD 07 FC F8-01 02 FD 07  ................
     000000F0:  FC F8 01 03-FD 07 FC F8-01 04 FD 07-FC F8 01 05  ................
     00000100:  FD 03 FE 04-00 42 FE 03-00 55 09 00-07 00 56 49  ..............VI
     00000110:  53 49 42 4C-45 0B 00 57-49 4E 44 4F-57 53 54 41  SIBLE..WINDOWSTA
     00000120:  54 45 02 00-46 30 02 00-46 31 02 00-46 32 02 00  TE..F0..F1..F2..
     00000130:  46 33 02 00-46 34 02 00-46 35 0A 00-53 4F 4D 45  F3..F4..F5..SOME
     00000140:  53 54 52 49-4E 47 63 00-61 00 61 00-61 00 61 00  STRING..........
     00000150:  61 00 D2 00-F1 00 E2 01-51 05 42 00-33 00 00 00  ................
     00000160:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 64 3A  ..............d:
     ............................................................................

     00000-00028 app head, 0x29 bytes
     00029-0004D fxp head, 0x25 bytes
     0004E-0004F size of main program: 0x00BA, 0x02 bytes
     00050-00109 main program, 0xBA bytes
     0010A-0010B number of names (variable etc.): 0x0009, 0x02 bytes
     0010C-00145 names, 0x3A bytes
     00146-0015D Lineno description (debug info), 0x18 bytes
     0015E-0016D Procedures/classes description (debug info), 0x10 bytes

     The size of the p-code of the line:
     INSERT INTO tttt (f0,f1,f2,f3,f4,f5) VALUES (CHRTRAN(somestring,'\','/'),1,2,3,4,5)
     is 0x0055 bytes.

     The size of the p-code of the line (from Mr. Pashka_J):
     RandFileName=sys(3)+"-"+left(sys(3),4)+"-"+left(sys(3),4)+"-"+left(sys(3),4)+"-"+sys(3)+left(sys(3),4)
     is 0x0055 bytes too.

     The size of the p-code of the line (from Mr. pat mazuel):
     Wait "Patientiez SVP N.. Piece " + ALLTRIM(tmp_file_grid.n_piece )+ " - N.. line " + ALLTRIM(STR(tmp_file_grid.ln_nb)) Window AT 10,150 Nowait NOCLEAR 
     is 0x0055 bytes too.

     I have done a lot of tests and found:
     If the size of the p-code is such as 0x0055, 0x0155, 0x0255 and etc.,
     then the breakpoint is incorrectly.


3. RESOLUTION:

     We can write some code to fix the BUG.

     1, Please refer to the file vfp9fix.h:

     //+--------------------------------------------------------------------------
     //
     //    File:        pro_ext.h
     //
     //    Copyright:    (c) 1999, Microsoft Corporation.
     //                All Rights Reserved.
     //                Information Contained Herein is Proprietary
     //                and Confidential.
     //
     //    Contents:    API Header for the Library Construction Kit
     //
     //    Notes: 
     //
     //---------------------------------------------------------------------------
     #ifndef PRO_EXT_INCLUDED
     #define PRO_EXT_INCLUDED

     #if defined(_MSC_VER)
     #pragma pack(push, 1)                 // Assume byte structure packing
     #endif

     #ifdef __cplusplus
     extern "C" {                        // Assume C declarations for C++
     #endif

     // Fastcall calling convention
     #define FASTCALL _fastcall

     // FPFI is a 32 bit pointer to a function returning an int
     typedef long (*FPFI)();

     // The FoxInfo structure contains the descriptions of the functions
     // contained in the library.
     typedef struct {
         char *    funcName;        /* Function name (all caps)                */
         FPFI        function;       /* Actual function address              */
         short        parmCount;        /* # parameters specified or a flag value */
         char *    parmTypes;        /* Parameter list description            */
     } FoxInfo;

     typedef struct _FoxTable {
         struct _FoxTable *nextLibrary;    /* Linked list of libraries        */
         short infoCount;            /* # of functions in this library        */
         FoxInfo *infoPtr;        /* Function list                        */
     } FoxTable;

     // An expression's value
     typedef struct {
         char                ev_type;
         char                ev_padding;
         short                ev_width;
         unsigned             ev_length;
         long                ev_long;
         double                ev_real;
         long                ev_currency;
         long                ev_currency2;
         unsigned            ev_handle;
         unsigned long        ev_object;
     } Value;

     // A reference to a database or memory variable
     typedef struct {
         char        l_type;
         short        l_where,        /* Database number or -1 for memory        */
                     l_NTI,            /* Variable name table offset            */
                     l_offset,        /* Index into database                    */
                     l_subs,            /* # subscripts specified 0 <= x <= 2    */
                     l_sub1, l_sub2; /* subscript integral values            */
     } Locator;

     typedef union {
         Value        val;
         Locator        loc;            /* An 'R' in l_type means the Locator    */
                                     /* part of this union is in use.        */
     } FoxParameter;

     // A paramter list to a library function.
     typedef struct {
         short         pCount;            /* Number of Parameters PASSED.            */
         FoxParameter    p[1];        /* pCount Parameters.                    */
     } ParamBlk;

     int FASTCALL _Execute(char *stmt);
     int FASTCALL _Evaluate(Value *val, char *expr);
     void FASTCALL _Error(int code);
     void FASTCALL _RetVal(Value *val);
     int FASTCALL _Store(Locator *loc, Value *val);
     int FASTCALL _Load(Locator *loc, Value *val);
     int FASTCALL _FindVar(int nti, int where, Locator *loc);
     int FASTCALL _NameTableIndex(char *name);

     #ifdef __cplusplus
     }                       // End of extern "C" {
     #endif

     #if defined(_MSC_VER)
     #pragma pack(pop)          // Restore structure packing
     #endif

     #endif                  // PRO_EXT_INCLUDED


     2, Please refer to the file vfp9fix.c:

     #include "vfp9fix.h"

     int __stdcall VirtualProtect(void *lpAddress, int dwSize, int flNewProtect, int *lpflOldProtect);

     void VFP9FixBreakPoint()
     {
         Value hmodule0retvalue;
         unsigned int hmodule0;
         unsigned int i;
         unsigned char *p1;
         unsigned char *p2;
         unsigned int OldProtect;
         _Execute("DECLARE integer GetModuleHandle IN win32api string lpfilename");
         _Evaluate(&hmodule0retvalue,"GetModuleHandle(_vfp.fullname)");
         hmodule0=hmodule0retvalue.ev_long;
         for (i=0x040000;i<0x280000;i++)
         {
             p1=hmodule0+i;
             if (*(p1+0x00)==0x8B &&
                 *(p1+0x01)==0x88 &&
                 *(p1+0x02)==0xE8 &&
                 *(p1+0x03)==0x02 &&
                 *(p1+0x04)==0x00 &&
                 *(p1+0x05)==0x00 &&
                 *(p1+0x06)==0x8B &&
                 *(p1+0x07)==0x11 &&
                 *(p1+0x08)==0x03 &&
                 *(p1+0x09)==0x90 &&
                 *(p1+0x0A)==0xF0 &&
                 *(p1+0x0B)==0x02 &&
                 *(p1+0x0C)==0x00 &&
                 *(p1+0x0D)==0x00 &&
                 *(p1+0x0E)==0x8B &&
                 *(p1+0x0F)==0x74 &&
                 *(p1+0x10)==0x24 &&
                 *(p1+0x11)==0x10 &&
                 *(p1+0x12)==0x8D &&
                 *(p1+0x13)==0x4B &&
                 *(p1+0x14)==0x02 &&
                 *(p1+0x15)==0x66 &&
                 *(p1+0x16)==0x89 &&
                 *(p1+0x17)==0x0A &&
                 *(p1+0x18)==0x8B &&
                 *(p1+0x19)==0xCB &&
                 *(p1+0x1A)==0x8D &&
                 *(p1+0x1B)==0x7A &&
                 *(p1+0x1C)==0x02 &&
                 *(p1+0x1D)==0x8B &&
                 *(p1+0x1E)==0xD1 &&
                 *(p1+0x1F)==0xC1 &&
                 *(p1+0x20)==0xE9 &&
                 *(p1+0x21)==0x02 &&
                 *(p1+0x22)==0xF3 &&
                 *(p1+0x23)==0xA5 &&
                 *(p1+0x24)==0x8B &&
                 *(p1+0x25)==0xCA &&
                 *(p1+0x26)==0x83 &&
                 *(p1+0x27)==0xE1 &&
                 *(p1+0x28)==0x03 &&
                 *(p1+0x29)==0xF3 &&
                 *(p1+0x2A)==0xA4 &&
                 *(p1+0x2B)==0x5F &&
                 *(p1+0x2C)==0x5E &&
                 *(p1+0x2D)==0x43 &&
                 *(p1+0x2E)==0x43 &&
                 *(p1+0x2F)==0x01 &&
                 *(p1+0x30)==0x98 &&
                 *(p1+0x31)==0xF0 &&
                 *(p1+0x32)==0x02 &&
                 *(p1+0x33)==0x00 &&
                 *(p1+0x34)==0x00 &&
                 *(p1+0x35)==0x8B &&
                 *(p1+0x36)==0xC3)
             {

                 // fix vfp9.exe, vfp9r.dll
                 // 00464C96: 8B88E8020000                 mov       ecx,[eax][0000002E8]
                 // 00464C9C: 8B11                         mov       edx,[ecx]
                 // 00464C9E: 0390F0020000                 add       edx,[eax][0000002F0]
                 // 00464CA4: 8B742410                     mov       esi,[esp][00010]
                 // 00464CA8: 8D4B02                       lea       ecx,[ebx][00002]
                 // 00464CAB: 66890A                       mov       [edx],cx
                 // 00464CAE: 8BCB                         mov       ecx,ebx
                 // 00464CB0: 8D7A02                       lea       edi,[edx][00002]
                 // 00464CB3: 8BD1                         mov       edx,ecx
                 // 00464CB5: C1E902                       shr       ecx,002
                 // 00464CB8: F3A5                         repe      movsd
                 // 00464CBA: 8BCA                         mov       ecx,edx
                 // 00464CBC: 83E103                       and       ecx,003
                 // 00464CBF: F3A4                         repe      movsb
                 // 00464CC1: 5F                           pop       edi
                 // 00464CC2: 5E                           pop       esi
                 // 00464CC3: 43                           inc       ebx
                 // 00464CC4: 43                           inc       ebx
                 // 00464CC5: 0198F0020000                 add       [eax][0000002F0],ebx
                 // 00464CCB: 8BC3                         mov       eax,ebx

                 // fix to:
                 // 00464C96: 8DB8E8020000                 lea       edi,[eax][0000002E8]
                 // 00464C9C: 8B0F                         mov       ecx,[edi]
                 // 00464C9E: 8B11                         mov       edx,[ecx]
                 // 00464CA0: 035708                       add       edx,[edi][00008]
                 // 00464CA3: 8B742410                     mov       esi,[esp][00010]
                 // 00464CA7: 80FB53                       cmp       bl,053
                 // 00464CAA: 7509                         jne       000464CB5
                 // 00464CAC: 8B4D00                       mov       ecx,[ebp][00000]
                 // 00464CAF: 3959F0                       cmp       [ecx][-0010],ebx
                 // 00464CB2: 7501                         jne       000464CB5
                 // 00464CB4: 43                           inc       ebx
                 // 00464CB5: 8D4B02                       lea       ecx,[ebx][00002]
                 // 00464CB8: 890A                         mov       [edx],ecx
                 // 00464CBA: 8BCB                         mov       ecx,ebx
                 // 00464CBC: 8D7A02                       lea       edi,[edx][00002]
                 // 00464CBF: F3A4                         repe      movsb
                 // 00464CC1: 5F                           pop       edi
                 // 00464CC2: 5E                           pop       esi
                 // 00464CC3: 43                           inc       ebx
                 // 00464CC4: 43                           inc       ebx
                 // 00464CC5: 0198F0020000                 add       [eax][0000002F0],ebx
                 // 00464CCB: 8BC3                         mov       eax,ebx
      
                 for (i=0x040000;i<0x280000;i++)
                 {
                     p2=hmodule0+i;
                     if (*(p2+0x00)==0x8B &&
                         *(p2+0x01)==0x88 &&
                         *(p2+0x02)==0x70 &&
                         *(p2+0x03)==0x02 &&
                         *(p2+0x04)==0x00 &&
                         *(p2+0x05)==0x00 &&
                         *(p2+0x06)==0x8B &&
                         *(p2+0x07)==0x11 &&
                         *(p2+0x08)==0x03 &&
                         *(p2+0x09)==0x90 &&
                         *(p2+0x0A)==0x7C &&
                         *(p2+0x0B)==0x02 &&
                         *(p2+0x0C)==0x00 &&
                         *(p2+0x0D)==0x00 &&
                         *(p2+0x0E)==0x8B &&
                         *(p2+0x0F)==0x74 &&
                         *(p2+0x10)==0x24 &&
                         *(p2+0x11)==0x10 &&
                         *(p2+0x12)==0x8D &&
                         *(p2+0x13)==0x4B &&
                         *(p2+0x14)==0x02 &&
                         *(p2+0x15)==0x66 &&
                         *(p2+0x16)==0x89 &&
                         *(p2+0x17)==0x0A &&
                         *(p2+0x18)==0x8B &&
                         *(p2+0x19)==0xCB &&
                         *(p2+0x1A)==0x8D &&
                         *(p2+0x1B)==0x7A &&
                         *(p2+0x1C)==0x02 &&
                         *(p2+0x1D)==0x8B &&
                         *(p2+0x1E)==0xD1 &&
                         *(p2+0x1F)==0xC1 &&
                         *(p2+0x20)==0xE9 &&
                         *(p2+0x21)==0x02 &&
                         *(p2+0x22)==0xF3 &&
                         *(p2+0x23)==0xA5 &&
                         *(p2+0x24)==0x8B &&
                         *(p2+0x25)==0xCA &&
                         *(p2+0x26)==0x83 &&
                         *(p2+0x27)==0xE1 &&
                         *(p2+0x28)==0x03 &&
                         *(p2+0x29)==0xF3 &&
                         *(p2+0x2A)==0xA4 &&
                         *(p2+0x2B)==0x5F &&
                         *(p2+0x2C)==0x5E &&
                         *(p2+0x2D)==0x43 &&
                         *(p2+0x2E)==0x43 &&
                         *(p2+0x2F)==0x01 &&
                         *(p2+0x30)==0x98 &&
                         *(p2+0x31)==0x7C &&
                         *(p2+0x32)==0x02 &&
                         *(p2+0x33)==0x00 &&
                         *(p2+0x34)==0x00 &&
                         *(p2+0x35)==0x8B &&
                         *(p2+0x36)==0xC3)
                     {

                         // fix vfp9.exe, vfp9r.dll
                         // 0054787A: 8B8870020000                 mov       ecx,[eax][000000270]
                         // 00547880: 8B11                         mov       edx,[ecx]
                         // 00547882: 03907C020000                 add       edx,[eax][00000027C]
                         // 00547888: 8B742410                     mov       esi,[esp][00010]
                         // 0054788C: 8D4B02                       lea       ecx,[ebx][00002]
                         // 0054788F: 66890A                       mov       [edx],cx
                         // 00547892: 8BCB                         mov       ecx,ebx
                         // 00547894: 8D7A02                       lea       edi,[edx][00002]
                         // 00547897: 8BD1                         mov       edx,ecx
                         // 00547899: C1E902                       shr       ecx,002
                         // 0054789C: F3A5                         repe      movsd
                         // 0054789E: 8BCA                         mov       ecx,edx
                         // 005478A0: 83E103                       and       ecx,003
                         // 005478A3: F3A4                         repe      movsb
                         // 005478A5: 5F                           pop       edi
                         // 005478A6: 5E                           pop       esi
                         // 005478A7: 43                           inc       ebx
                         // 005478A8: 43                           inc       ebx
                         // 005478A9: 01987C020000                 add       [eax][00000027C],ebx
                         // 005478AF: 8BC3                         mov       eax,ebx

                         // fix to:
                         // 0054787A: 8DB870020000                 lea       edi,[eax][000000270]
                         // 00547880: 8B0F                         mov       ecx,[edi]
                         // 00547882: 8B11                         mov       edx,[ecx]
                         // 00547884: 03570C                       add       edx,[edi][0000C]
                         // 00547887: 8B742410                     mov       esi,[esp][00010]
                         // 0054788B: 80FB53                       cmp       bl,053
                         // 0054788E: 7509                         jne       000547899
                         // 00547890: 8B4D00                       mov       ecx,[ebp][00000]
                         // 00547893: 3959F0                       cmp       [ecx][-0010],ebx
                         // 00547896: 7501                         jne       000547899
                         // 00547898: 43                           inc       ebx
                         // 00547899: 8D4B02                       lea       ecx,[ebx][00002]
                         // 0054789C: 890A                         mov       [edx],ecx
                         // 0054789E: 8BCB                         mov       ecx,ebx
                         // 005478A0: 8D7A02                       lea       edi,[edx][00002]
                         // 005478A3: F3A4                         repe      movsb
                         // 005478A5: 5F                           pop       edi
                         // 005478A6: 5E                           pop       esi
                         // 005478A7: 43                           inc       ebx
                         // 005478A8: 43                           inc       ebx
                         // 005478A9: 01987C020000                 add       [eax][00000027C],ebx
                         // 005478AF: 8BC3                         mov       eax,ebx

                         // _Execute("_SCREEN.VISIBLE=.T.");
                         // _Execute("WAIT WIND 'VFP9FixBreakPoint OK.'");

                         OldProtect=0x20; // PAGE_EXECUTE_READ
                         VirtualProtect(p1,0x30,0x40,&OldProtect); // PAGE_EXECUTE_READWRITE
                         *(p1+0x00)=0x8D;
                         *(p1+0x01)=0xB8;
                         *(p1+0x02)=0xE8;
                         *(p1+0x03)=0x02;
                         *(p1+0x04)=0x00;
                         *(p1+0x05)=0x00;
                         *(p1+0x06)=0x8B;
                         *(p1+0x07)=0x0F;
                         *(p1+0x08)=0x8B;
                         *(p1+0x09)=0x11;
                         *(p1+0x0A)=0x03;
                         *(p1+0x0B)=0x57;
                         *(p1+0x0C)=0x08;
                         *(p1+0x0D)=0x8B;
                         *(p1+0x0E)=0x74;
                         *(p1+0x0F)=0x24;
                         *(p1+0x10)=0x10;
                         *(p1+0x11)=0x80;
                         *(p1+0x12)=0xFB;
                         *(p1+0x13)=0x53;
                         *(p1+0x14)=0x75;
                         *(p1+0x15)=0x09;
                         *(p1+0x16)=0x8B;
                         *(p1+0x17)=0x4D;
                         *(p1+0x18)=0x00;
                         *(p1+0x19)=0x39;
                         *(p1+0x1A)=0x59;
                         *(p1+0x1B)=0xF0;
                         *(p1+0x1C)=0x75;
                         *(p1+0x1D)=0x01;
                         *(p1+0x1E)=0x43;
                         *(p1+0x1F)=0x8D;
                         *(p1+0x20)=0x4B;
                         *(p1+0x21)=0x02;
                         *(p1+0x22)=0x89;
                         *(p1+0x23)=0x0A;
                         *(p1+0x24)=0x8B;
                         *(p1+0x25)=0xCB;
                         *(p1+0x26)=0x8D;
                         *(p1+0x27)=0x7A;
                         *(p1+0x28)=0x02;
                         VirtualProtect(p1,0x30,OldProtect,&OldProtect);

                         OldProtect=0x20; // PAGE_EXECUTE_READ
                         VirtualProtect(p2,0x30,0x40,&OldProtect); // PAGE_EXECUTE_READWRITE
                         *(p2+0x00)=0x8D;
                         *(p2+0x01)=0xB8;
                         *(p2+0x02)=0x70;
                         *(p2+0x03)=0x02;
                         *(p2+0x04)=0x00;
                         *(p2+0x05)=0x00;
                         *(p2+0x06)=0x8B;
                         *(p2+0x07)=0x0F;
                         *(p2+0x08)=0x8B;
                         *(p2+0x09)=0x11;
                         *(p2+0x0A)=0x03;
                         *(p2+0x0B)=0x57;
                         *(p2+0x0C)=0x0C;
                         *(p2+0x0D)=0x8B;
                         *(p2+0x0E)=0x74;
                         *(p2+0x0F)=0x24;
                         *(p2+0x10)=0x10;
                         *(p2+0x11)=0x80;
                         *(p2+0x12)=0xFB;
                         *(p2+0x13)=0x53;
                         *(p2+0x14)=0x75;
                         *(p2+0x15)=0x09;
                         *(p2+0x16)=0x8B;
                         *(p2+0x17)=0x4D;
                         *(p2+0x18)=0x00;
                         *(p2+0x19)=0x39;
                         *(p2+0x1A)=0x59;
                         *(p2+0x1B)=0xF0;
                         *(p2+0x1C)=0x75;
                         *(p2+0x1D)=0x01;
                         *(p2+0x1E)=0x43;
                         *(p2+0x1F)=0x8D;
                         *(p2+0x20)=0x4B;
                         *(p2+0x21)=0x02;
                         *(p2+0x22)=0x89;
                         *(p2+0x23)=0x0A;
                         *(p2+0x24)=0x8B;
                         *(p2+0x25)=0xCB;
                         *(p2+0x26)=0x8D;
                         *(p2+0x27)=0x7A;
                         *(p2+0x28)=0x02;
                         VirtualProtect(p2,0x30,OldProtect,&OldProtect);
                         break;
                     }
                 }
                 break;
             }
         }
     }

     FoxInfo myFoxInfo[]={
     {"VFP9FixBreakPoint",(FPFI)VFP9FixBreakPoint,0,""},
     };

     FoxTable _FoxTable={
     (FoxTable *)0,sizeof(myFoxInfo)/sizeof(FoxInfo),myFoxInfo
     };


     3, Please refer to the file make.bat:

     @echo off

     rem ;-----------------------------------------------;
     rem ;       VFP9fix Maker Program                   ;
     rem ;           Make.bat                            ;
     rem ;       (C)Mr. Chen, 2009.11                    ;
     rem ;       E-mail: ccb2000@163.com                 ;
     rem ;-----------------------------------------------;

     rem NMAKE /f "vfp9fix.mak" CFG="vfp9fix - Win32 Release"

     if exist .\vfp9fix.dll del .\vfp9fix.dll
     if exist .\vfp9fix.obj del .\vfp9fix.obj
     if exist .\vfp9fix.lib del .\vfp9fix.lib
     if exist .\vfp9fix.exp del .\vfp9fix.exp
     if exist .\vfp9fix.pch del .\vfp9fix.pch

     cl /nologo /Gr /MD /w /W0 /Ox /Ob1 /Os /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Zm1000 /c vfp9fix.c
     if not exist .\vfp9fix.obj pause

     link kernel32.lib user32.lib uuid.lib winapims.lib /nologo /subsystem:windows /dll /incremental:no
     /machine:I386 /out:".\vfp9fix.dll" /implib:".\vfp9fix.lib" ".\vfp9fix.obj"


     Then run make.bat, we can build a VFP API Library file: vfp9fix.dll.


     4, Please refer to the file f_vfp9fixbreakpointwithdll.prg:

     *PROC f_vfp9fixbreakpointwithdll

     * VFP 9.0 FIX - INVISIBLE BREAKPOINT with vfp9fix.dll
     * ccb2000@163.com, 2012.5

     PRIVATE m.q_vfp9fixbreakpoint
     m.q_vfp9fixbreakpoint=.T.

     IF (ROUND(VAL(CHRTRAN(UPPE(VERSION()),"MICROSOFTVISUALFOXPRO","")),2)=9.0.AND.VERSION(2)>0)

        PRIVATE m.q_errnum,m.q_erroron
        m.q_errnum=0
        m.q_erroron=ON("ERROR")
        ON ERROR m.q_errnum=ERROR()
        SET LIBRARY TO ("vfp9fix.dll") ADDITIVE
        ON ERROR &q_erroron

        IF .F.
           PUBLIC vfp9fixbreakpoint(1)
        ENDI

        IF m.q_errnum#0
           m.q_vfp9fixbreakpoint=.F.
           RETU m.q_vfp9fixbreakpoint
        ENDI

        PRIVATE m.q_errnum,m.q_erroron
        m.q_errnum=0
        m.q_erroron=ON("ERROR")
        ON ERROR m.q_errnum=ERROR()
        =vfp9fixbreakpoint()
        ON ERROR &q_erroron

        IF m.q_errnum#0
           m.q_vfp9fixbreakpoint=.F.
           RETU m.q_vfp9fixbreakpoint
        ENDI

        PRIVATE m.q_errnum,m.q_erroron
        m.q_errnum=0
        m.q_erroron=ON("ERROR")
        ON ERROR m.q_errnum=ERROR()
        RELEASE LIBRARY ("vfp9fix.dll")
        ON ERROR &q_erroron

        IF m.q_errnum#0
           m.q_vfp9fixbreakpoint=.F.
           RETU m.q_vfp9fixbreakpoint
        ENDI

        m.q_vfp9fixbreakpoint=.T.
        RETU m.q_vfp9fixbreakpoint

     ENDI

     m.q_vfp9fixbreakpoint=.T.
     RETU m.q_vfp9fixbreakpoint

     * END OF PROC F_VFP9FIXBREAKPOINTWITHDLL.


     5, Please refer to the file f_vfp9fixbreakpoint.prg:

     *PROC f_vfp9fixbreakpoint

     * VFP 9.0 FIX - INVISIBLE BREAKPOINT
     * ccb2000@163.com, 2012.5

     PRIVATE m.q_vfp9fixbreakpoint
     m.q_vfp9fixbreakpoint=.T.

     IF !(ROUND(VAL(CHRTRAN(UPPE(VERSION()),"MICROSOFTVISUALFOXPRO","")),2)=9.0.AND.VERSION(2)>0)
        m.q_vfp9fixbreakpoint=.T.
        RETU m.q_vfp9fixbreakpoint
     ENDI

     DECLARE INTEGER "GetModuleHandle" IN win32api ;
        STRING lpfilename
     DECLARE INTEGER "GetCurrentProcess" IN win32api
     DECLARE INTEGER "ReadProcessMemory" IN win32api ;
        LONG    hprocess,;
        INTEGER lpbaseaddress,;
        STRING @lpbuffer,;
        INTEGER nsize,;
        INTEGER lpnumberofbytesread
     DECLARE INTEGER "WriteProcessMemory" IN win32api ;
        LONG    hprocess,;
        INTEGER lpbaseaddress,;
        STRING lpbuffer,;
        INTEGER nsize,;
        INTEGER lpnumberofbyteswritten
     DECLARE INTEGER "VirtualProtect" IN win32api ;
        INTEGER lpaddress,;
        INTEGER dwsize,;
        INTEGER flnewprotect,;
        INTEGER @lpfloldprotect

     IF .F.
        PUBLIC getmodulehandle(1)
        PUBLIC getcurrentprocess(1)
        PUBLIC readprocessmemory(1)
        PUBLIC writeprocessmemory(1)
        PUBLIC virtualprotect(1)
     ENDIF

     PRIVATE m.q_hmodule0
     m.q_hmodule0=0
     m.q_hmodule0=getmodulehandle(_VFP.FULLNAME)
     IF !m.q_hmodule0>0
        m.q_vfp9fixbreakpoint=.F.
        RETU m.q_vfp9fixbreakpoint
     ENDIF


     * for (i=0x040000;i<0x280000;i++)
     * {
     *     p1=hmodule0+i;
     *     if (*(p1+0x00)==0x8B &&
     *         *(p1+0x01)==0x88 &&
     *         *(p1+0x02)==0xE8 &&
     *         *(p1+0x03)==0x02 &&
     *         *(p1+0x04)==0x00 &&
     *         *(p1+0x05)==0x00 &&
     *         *(p1+0x06)==0x8B &&
     *         *(p1+0x07)==0x11 &&
     *         *(p1+0x08)==0x03 &&
     *         *(p1+0x09)==0x90 &&
     *         *(p1+0x0A)==0xF0 &&
     *         *(p1+0x0B)==0x02 &&
     *         *(p1+0x0C)==0x00 &&
     *         *(p1+0x0D)==0x00 &&
     *         *(p1+0x0E)==0x8B &&
     *         *(p1+0x0F)==0x74 &&
     *         *(p1+0x10)==0x24 &&
     *         *(p1+0x11)==0x10 &&
     *         *(p1+0x12)==0x8D &&
     *         *(p1+0x13)==0x4B &&
     *         *(p1+0x14)==0x02 &&
     *         *(p1+0x15)==0x66 &&
     *         *(p1+0x16)==0x89 &&
     *         *(p1+0x17)==0x0A &&
     *         *(p1+0x18)==0x8B &&
     *         *(p1+0x19)==0xCB &&
     *         *(p1+0x1A)==0x8D &&
     *         *(p1+0x1B)==0x7A &&
     *         *(p1+0x1C)==0x02 &&
     *         *(p1+0x1D)==0x8B &&
     *         *(p1+0x1E)==0xD1 &&
     *         *(p1+0x1F)==0xC1 &&
     *         *(p1+0x20)==0xE9 &&
     *         *(p1+0x21)==0x02 &&
     *         *(p1+0x22)==0xF3 &&
     *         *(p1+0x23)==0xA5 &&
     *         *(p1+0x24)==0x8B &&
     *         *(p1+0x25)==0xCA &&
     *         *(p1+0x26)==0x83 &&
     *         *(p1+0x27)==0xE1 &&
     *         *(p1+0x28)==0x03 &&
     *         *(p1+0x29)==0xF3 &&
     *         *(p1+0x2A)==0xA4 &&
     *         *(p1+0x2B)==0x5F &&
     *         *(p1+0x2C)==0x5E &&
     *         *(p1+0x2D)==0x43 &&
     *         *(p1+0x2E)==0x43 &&
     *         *(p1+0x2F)==0x01 &&
     *         *(p1+0x30)==0x98 &&
     *         *(p1+0x31)==0xF0 &&
     *         *(p1+0x32)==0x02 &&
     *         *(p1+0x33)==0x00 &&
     *         *(p1+0x34)==0x00 &&
     *         *(p1+0x35)==0x8B &&
     *         *(p1+0x36)==0xC3)
     *     {
     *
     *         // fix vfp9.exe, vfp9r.dll
     *         // 00464C96: 8B88E8020000                 mov       ecx,[eax][0000002E8]
     *         // 00464C9C: 8B11                         mov       edx,[ecx]
     *         // 00464C9E: 0390F0020000                 add       edx,[eax][0000002F0]
     *         // 00464CA4: 8B742410                     mov       esi,[esp][00010]
     *         // 00464CA8: 8D4B02                       lea       ecx,[ebx][00002]
     *         // 00464CAB: 66890A                       mov       [edx],cx
     *         // 00464CAE: 8BCB                         mov       ecx,ebx
     *         // 00464CB0: 8D7A02                       lea       edi,[edx][00002]
     *         // 00464CB3: 8BD1                         mov       edx,ecx
     *         // 00464CB5: C1E902                       shr       ecx,002
     *         // 00464CB8: F3A5                         repe      movsd
     *         // 00464CBA: 8BCA                         mov       ecx,edx
     *         // 00464CBC: 83E103                       and       ecx,003
     *         // 00464CBF: F3A4                         repe      movsb
     *         // 00464CC1: 5F                           pop       edi
     *         // 00464CC2: 5E                           pop       esi
     *         // 00464CC3: 43                           inc       ebx
     *         // 00464CC4: 43                           inc       ebx
     *         // 00464CC5: 0198F0020000                 add       [eax][0000002F0],ebx
     *         // 00464CCB: 8BC3                         mov       eax,ebx
     *
     *         // fix to:
     *         // 00464C96: 8DB8E8020000                 lea       edi,[eax][0000002E8]
     *         // 00464C9C: 8B0F                         mov       ecx,[edi]
     *         // 00464C9E: 8B11                         mov       edx,[ecx]
     *         // 00464CA0: 035708                       add       edx,[edi][00008]
     *         // 00464CA3: 8B742410                     mov       esi,[esp][00010]
     *         // 00464CA7: 80FB53                       cmp       bl,053
     *         // 00464CAA: 7509                         jne       000464CB5
     *         // 00464CAC: 8B4D00                       mov       ecx,[ebp][00000]
     *         // 00464CAF: 3959F0                       cmp       [ecx][-0010],ebx
     *         // 00464CB2: 7501                         jne       000464CB5
     *         // 00464CB4: 43                           inc       ebx
     *         // 00464CB5: 8D4B02                       lea       ecx,[ebx][00002]
     *         // 00464CB8: 890A                         mov       [edx],ecx
     *         // 00464CBA: 8BCB                         mov       ecx,ebx
     *         // 00464CBC: 8D7A02                       lea       edi,[edx][00002]
     *         // 00464CBF: F3A4                         repe      movsb
     *         // 00464CC1: 5F                           pop       edi
     *         // 00464CC2: 5E                           pop       esi
     *         // 00464CC3: 43                           inc       ebx
     *         // 00464CC4: 43                           inc       ebx
     *         // 00464CC5: 0198F0020000                 add       [eax][0000002F0],ebx
     *         // 00464CCB: 8BC3                         mov       eax,ebx

     PRIVATE m.q_str1
     m.q_str1=REPL(CHR(0),0x280000-0x040000)
     =readprocessmemory(getcurrentprocess(),m.q_hmodule0+0x040000,@m.q_str1,LEN(m.q_str1),0)

     PRIVATE m.q_p1_nn
     m.q_p1_nn=1

     DO WHILE .T.

        PRIVATE m.q_p1
        m.q_p1=AT(CHR(0x8b)+;
           CHR(0x88)+;
           CHR(0xe8)+;
           CHR(0x02)+;
           CHR(0x00)+;
           CHR(0x00)+;
           CHR(0x8b)+;
           CHR(0x11)+;
           CHR(0x03)+;
           CHR(0x90)+;
           CHR(0xf0)+;
           CHR(0x02)+;
           CHR(0x00)+;
           CHR(0x00)+;
           CHR(0x8b)+;
           CHR(0x74)+;
           CHR(0x24)+;
           CHR(0x10)+;
           CHR(0x8d)+;
           CHR(0x4b)+;
           CHR(0x02)+;
           CHR(0x66)+;
           CHR(0x89)+;
           CHR(0x0a)+;
           CHR(0x8b)+;
           CHR(0xcb)+;
           CHR(0x8d)+;
           CHR(0x7a)+;
           CHR(0x02)+;
           CHR(0x8b)+;
           CHR(0xd1)+;
           CHR(0xc1)+;
           CHR(0xe9)+;
           CHR(0x02)+;
           CHR(0xf3)+;
           CHR(0xa5)+;
           CHR(0x8b)+;
           CHR(0xca)+;
           CHR(0x83)+;
           CHR(0xe1)+;
           CHR(0x03)+;
           CHR(0xf3)+;
           CHR(0xa4)+;
           CHR(0x5f)+;
           CHR(0x5e)+;
           CHR(0x43)+;
           CHR(0x43)+;
           CHR(0x01)+;
           CHR(0x98)+;
           CHR(0xf0)+;
           CHR(0x02)+;
           CHR(0x00)+;
           CHR(0x00)+;
           CHR(0x8b)+;
           CHR(0xc3),m.q_str1,m.q_p1_nn)
        IF !m.q_p1>0
           m.q_vfp9fixbreakpoint=.F.
           RETU m.q_vfp9fixbreakpoint
        ENDIF
        m.q_p1=m.q_p1-0x00

        IF !(SUBS(m.q_str1,m.q_p1+0x00,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x01,1)==CHR(0x88).AND.;
              SUBS(m.q_str1,m.q_p1+0x02,1)==CHR(0xe8).AND.;
              SUBS(m.q_str1,m.q_p1+0x03,1)==CHR(0x02).AND.;
              SUBS(m.q_str1,m.q_p1+0x04,1)==CHR(0x00).AND.;
              SUBS(m.q_str1,m.q_p1+0x05,1)==CHR(0x00).AND.;
              SUBS(m.q_str1,m.q_p1+0x06,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x07,1)==CHR(0x11).AND.;
              SUBS(m.q_str1,m.q_p1+0x08,1)==CHR(0x03).AND.;
              SUBS(m.q_str1,m.q_p1+0x09,1)==CHR(0x90).AND.;
              SUBS(m.q_str1,m.q_p1+0x0a,1)==CHR(0xf0).AND.;
              SUBS(m.q_str1,m.q_p1+0x0b,1)==CHR(0x02).AND.;
              SUBS(m.q_str1,m.q_p1+0x0c,1)==CHR(0x00).AND.;
              SUBS(m.q_str1,m.q_p1+0x0d,1)==CHR(0x00).AND.;
              SUBS(m.q_str1,m.q_p1+0x0e,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x0f,1)==CHR(0x74).AND.;
              SUBS(m.q_str1,m.q_p1+0x10,1)==CHR(0x24).AND.;
              SUBS(m.q_str1,m.q_p1+0x11,1)==CHR(0x10).AND.;
              SUBS(m.q_str1,m.q_p1+0x12,1)==CHR(0x8d).AND.;
              SUBS(m.q_str1,m.q_p1+0x13,1)==CHR(0x4b).AND.;
              SUBS(m.q_str1,m.q_p1+0x14,1)==CHR(0x02).AND.;
              SUBS(m.q_str1,m.q_p1+0x15,1)==CHR(0x66).AND.;
              SUBS(m.q_str1,m.q_p1+0x16,1)==CHR(0x89).AND.;
              SUBS(m.q_str1,m.q_p1+0x17,1)==CHR(0x0a).AND.;
              SUBS(m.q_str1,m.q_p1+0x18,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x19,1)==CHR(0xcb).AND.;
              SUBS(m.q_str1,m.q_p1+0x1a,1)==CHR(0x8d).AND.;
              SUBS(m.q_str1,m.q_p1+0x1b,1)==CHR(0x7a).AND.;
              SUBS(m.q_str1,m.q_p1+0x1c,1)==CHR(0x02).AND.;
              SUBS(m.q_str1,m.q_p1+0x1d,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x1e,1)==CHR(0xd1).AND.;
              SUBS(m.q_str1,m.q_p1+0x1f,1)==CHR(0xc1).AND.;
              SUBS(m.q_str1,m.q_p1+0x20,1)==CHR(0xe9).AND.;
              SUBS(m.q_str1,m.q_p1+0x21,1)==CHR(0x02).AND.;
              SUBS(m.q_str1,m.q_p1+0x22,1)==CHR(0xf3).AND.;
              SUBS(m.q_str1,m.q_p1+0x23,1)==CHR(0xa5).AND.;
              SUBS(m.q_str1,m.q_p1+0x24,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x25,1)==CHR(0xca).AND.;
              SUBS(m.q_str1,m.q_p1+0x26,1)==CHR(0x83).AND.;
              SUBS(m.q_str1,m.q_p1+0x27,1)==CHR(0xe1).AND.;
              SUBS(m.q_str1,m.q_p1+0x28,1)==CHR(0x03).AND.;
              SUBS(m.q_str1,m.q_p1+0x29,1)==CHR(0xf3).AND.;
              SUBS(m.q_str1,m.q_p1+0x2a,1)==CHR(0xa4).AND.;
              SUBS(m.q_str1,m.q_p1+0x2b,1)==CHR(0x5f).AND.;
              SUBS(m.q_str1,m.q_p1+0x2c,1)==CHR(0x5e).AND.;
              SUBS(m.q_str1,m.q_p1+0x2d,1)==CHR(0x43).AND.;
              SUBS(m.q_str1,m.q_p1+0x2e,1)==CHR(0x43).AND.;
              SUBS(m.q_str1,m.q_p1+0x2f,1)==CHR(0x01).AND.;
              SUBS(m.q_str1,m.q_p1+0x30,1)==CHR(0x98).AND.;
              SUBS(m.q_str1,m.q_p1+0x31,1)==CHR(0xf0).AND.;
              SUBS(m.q_str1,m.q_p1+0x32,1)==CHR(0x02).AND.;
              SUBS(m.q_str1,m.q_p1+0x33,1)==CHR(0x00).AND.;
              SUBS(m.q_str1,m.q_p1+0x34,1)==CHR(0x00).AND.;
              SUBS(m.q_str1,m.q_p1+0x35,1)==CHR(0x8b).AND.;
              SUBS(m.q_str1,m.q_p1+0x36,1)==CHR(0xc3))
           m.q_p1_nn=m.q_p1_nn+1
           LOOP
        ENDIF

        EXIT

     ENDDO


     * for (i=0x040000;i<0x280000;i++)
     * {
     *     p2=hmodule0+i;
     *     if (*(p2+0x00)==0x8B &&
     *         *(p2+0x01)==0x88 &&
     *         *(p2+0x02)==0x70 &&
     *         *(p2+0x03)==0x02 &&
     *         *(p2+0x04)==0x00 &&
     *         *(p2+0x05)==0x00 &&
     *         *(p2+0x06)==0x8B &&
     *         *(p2+0x07)==0x11 &&
     *         *(p2+0x08)==0x03 &&
     *         *(p2+0x09)==0x90 &&
     *         *(p2+0x0A)==0x7C &&
     *         *(p2+0x0B)==0x02 &&
     *         *(p2+0x0C)==0x00 &&
     *         *(p2+0x0D)==0x00 &&
     *         *(p2+0x0E)==0x8B &&
     *         *(p2+0x0F)==0x74 &&
     *         *(p2+0x10)==0x24 &&
     *         *(p2+0x11)==0x10 &&
     *         *(p2+0x12)==0x8D &&
     *         *(p2+0x13)==0x4B &&
     *         *(p2+0x14)==0x02 &&
     *         *(p2+0x15)==0x66 &&
     *         *(p2+0x16)==0x89 &&
     *         *(p2+0x17)==0x0A &&
     *         *(p2+0x18)==0x8B &&
     *         *(p2+0x19)==0xCB &&
     *         *(p2+0x1A)==0x8D &&
     *         *(p2+0x1B)==0x7A &&
     *         *(p2+0x1C)==0x02 &&
     *         *(p2+0x1D)==0x8B &&
     *         *(p2+0x1E)==0xD1 &&
     *         *(p2+0x1F)==0xC1 &&
     *         *(p2+0x20)==0xE9 &&
     *         *(p2+0x21)==0x02 &&
     *         *(p2+0x22)==0xF3 &&
     *         *(p2+0x23)==0xA5 &&
     *         *(p2+0x24)==0x8B &&
     *         *(p2+0x25)==0xCA &&
     *         *(p2+0x26)==0x83 &&
     *         *(p2+0x27)==0xE1 &&
     *         *(p2+0x28)==0x03 &&
     *         *(p2+0x29)==0xF3 &&
     *         *(p2+0x2A)==0xA4 &&
     *         *(p2+0x2B)==0x5F &&
     *         *(p2+0x2C)==0x5E &&
     *         *(p2+0x2D)==0x43 &&
     *         *(p2+0x2E)==0x43 &&
     *         *(p2+0x2F)==0x01 &&
     *         *(p2+0x30)==0x98 &&
     *         *(p2+0x31)==0x7C &&
     *         *(p2+0x32)==0x02 &&
     *         *(p2+0x33)==0x00 &&
     *         *(p2+0x34)==0x00 &&
     *         *(p2+0x35)==0x8B &&
     *         *(p2+0x36)==0xC3)
     *     {
     *
     *         // fix vfp9.exe, vfp9r.dll
     *         // 0054787A: 8B8870020000                 mov       ecx,[eax][000000270]
     *         // 00547880: 8B11                         mov       edx,[ecx]
     *         // 00547882: 03907C020000                 add       edx,[eax][00000027C]
     *         // 00547888: 8B742410                     mov       esi,[esp][00010]
     *         // 0054788C: 8D4B02                       lea       ecx,[ebx][00002]
     *         // 0054788F: 66890A                       mov       [edx],cx
     *         // 00547892: 8BCB                         mov       ecx,ebx
     *         // 00547894: 8D7A02                       lea       edi,[edx][00002]
     *         // 00547897: 8BD1                         mov       edx,ecx
     *         // 00547899: C1E902                       shr       ecx,002
     *         // 0054789C: F3A5                         repe      movsd
     *         // 0054789E: 8BCA                         mov       ecx,edx
     *         // 005478A0: 83E103                       and       ecx,003
     *         // 005478A3: F3A4                         repe      movsb
     *         // 005478A5: 5F                           pop       edi
     *         // 005478A6: 5E                           pop       esi
     *         // 005478A7: 43                           inc       ebx
     *         // 005478A8: 43                           inc       ebx
     *         // 005478A9: 01987C020000                 add       [eax][00000027C],ebx
     *         // 005478AF: 8BC3                         mov       eax,ebx
     *
     *         // fix to:
     *         // 0054787A: 8DB870020000                 lea       edi,[eax][000000270]
     *         // 00547880: 8B0F                         mov       ecx,[edi]
     *         // 00547882: 8B11                         mov       edx,[ecx]
     *         // 00547884: 03570C                       add       edx,[edi][0000C]
     *         // 00547887: 8B742410                     mov       esi,[esp][00010]
     *         // 0054788B: 80FB53                       cmp       bl,053
     *         // 0054788E: 7509                         jne       000547899
     *         // 00547890: 8B4D00                       mov       ecx,[ebp][00000]
     *         // 00547893: 3959F0                       cmp       [ecx][-0010],ebx
     *         // 00547896: 7501                         jne       000547899
     *         // 00547898: 43                           inc       ebx
     *         // 00547899: 8D4B02                       lea       ecx,[ebx][00002]
     *         // 0054789C: 890A                         mov       [edx],ecx
     *         // 0054789E: 8BCB                         mov       ecx,ebx
     *         // 005478A0: 8D7A02                       lea       edi,[edx][00002]
     *         // 005478A3: F3A4                         repe      movsb
     *         // 005478A5: 5F                           pop       edi
     *         // 005478A6: 5E                           pop       esi
     *         // 005478A7: 43                           inc       ebx
     *         // 005478A8: 43                           inc       ebx
     *         // 005478A9: 01987C020000                 add       [eax][00000027C],ebx
     *         // 005478AF: 8BC3                         mov       eax,ebx

     PRIVATE m.q_str2
     m.q_str2=REPL(CHR(0),0x280000-0x040000)
     =readprocessmemory(getcurrentprocess(),m.q_hmodule0+0x040000,@m.q_str2,LEN(m.q_str2),0)

     PRIVATE m.q_p2_nn
     m.q_p2_nn=1

     DO WHILE .T.

        PRIVATE m.q_p2
        m.q_p2=AT(CHR(0x8b)+;
           CHR(0x88)+;
           CHR(0x70)+;
           CHR(0x02)+;
           CHR(0x00)+;
           CHR(0x00)+;
           CHR(0x8b)+;
           CHR(0x11)+;
           CHR(0x03)+;
           CHR(0x90)+;
           CHR(0x7c)+;
           CHR(0x02)+;
           CHR(0x00)+;
           CHR(0x00)+;
           CHR(0x8b)+;
           CHR(0x74)+;
           CHR(0x24)+;
           CHR(0x10)+;
           CHR(0x8d)+;
           CHR(0x4b)+;
           CHR(0x02)+;
           CHR(0x66)+;
           CHR(0x89)+;
           CHR(0x0a)+;
           CHR(0x8b)+;
           CHR(0xcb)+;
           CHR(0x8d)+;
           CHR(0x7a)+;
           CHR(0x02)+;
           CHR(0x8b)+;
           CHR(0xd1)+;
           CHR(0xc1)+;
           CHR(0xe9)+;
           CHR(0x02)+;
           CHR(0xf3)+;
           CHR(0xa5)+;
           CHR(0x8b)+;
           CHR(0xca)+;
           CHR(0x83)+;
           CHR(0xe1)+;
           CHR(0x03)+;
           CHR(0xf3)+;
           CHR(0xa4)+;
           CHR(0x5f)+;
           CHR(0x5e)+;
           CHR(0x43)+;
           CHR(0x43)+;
           CHR(0x01)+;
           CHR(0x98)+;
           CHR(0x7c)+;
           CHR(0x02)+;
           CHR(0x00)+;
           CHR(0x00)+;
           CHR(0x8b)+;
           CHR(0xc3),m.q_str2,m.q_p2_nn)
        IF !m.q_p2>0
           m.q_vfp9fixbreakpoint=.F.
           RETU m.q_vfp9fixbreakpoint
        ENDIF
        m.q_p2=m.q_p2-0x00

        IF !(SUBS(m.q_str2,m.q_p2+0x00,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x01,1)==CHR(0x88).AND.;
              SUBS(m.q_str2,m.q_p2+0x02,1)==CHR(0x70).AND.;
              SUBS(m.q_str2,m.q_p2+0x03,1)==CHR(0x02).AND.;
              SUBS(m.q_str2,m.q_p2+0x04,1)==CHR(0x00).AND.;
              SUBS(m.q_str2,m.q_p2+0x05,1)==CHR(0x00).AND.;
              SUBS(m.q_str2,m.q_p2+0x06,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x07,1)==CHR(0x11).AND.;
              SUBS(m.q_str2,m.q_p2+0x08,1)==CHR(0x03).AND.;
              SUBS(m.q_str2,m.q_p2+0x09,1)==CHR(0x90).AND.;
              SUBS(m.q_str2,m.q_p2+0x0a,1)==CHR(0x7c).AND.;
              SUBS(m.q_str2,m.q_p2+0x0b,1)==CHR(0x02).AND.;
              SUBS(m.q_str2,m.q_p2+0x0c,1)==CHR(0x00).AND.;
              SUBS(m.q_str2,m.q_p2+0x0d,1)==CHR(0x00).AND.;
              SUBS(m.q_str2,m.q_p2+0x0e,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x0f,1)==CHR(0x74).AND.;
              SUBS(m.q_str2,m.q_p2+0x10,1)==CHR(0x24).AND.;
              SUBS(m.q_str2,m.q_p2+0x11,1)==CHR(0x10).AND.;
              SUBS(m.q_str2,m.q_p2+0x12,1)==CHR(0x8d).AND.;
              SUBS(m.q_str2,m.q_p2+0x13,1)==CHR(0x4b).AND.;
              SUBS(m.q_str2,m.q_p2+0x14,1)==CHR(0x02).AND.;
              SUBS(m.q_str2,m.q_p2+0x15,1)==CHR(0x66).AND.;
              SUBS(m.q_str2,m.q_p2+0x16,1)==CHR(0x89).AND.;
              SUBS(m.q_str2,m.q_p2+0x17,1)==CHR(0x0a).AND.;
              SUBS(m.q_str2,m.q_p2+0x18,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x19,1)==CHR(0xcb).AND.;
              SUBS(m.q_str2,m.q_p2+0x1a,1)==CHR(0x8d).AND.;
              SUBS(m.q_str2,m.q_p2+0x1b,1)==CHR(0x7a).AND.;
              SUBS(m.q_str2,m.q_p2+0x1c,1)==CHR(0x02).AND.;
              SUBS(m.q_str2,m.q_p2+0x1d,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x1e,1)==CHR(0xd1).AND.;
              SUBS(m.q_str2,m.q_p2+0x1f,1)==CHR(0xc1).AND.;
              SUBS(m.q_str2,m.q_p2+0x20,1)==CHR(0xe9).AND.;
              SUBS(m.q_str2,m.q_p2+0x21,1)==CHR(0x02).AND.;
              SUBS(m.q_str2,m.q_p2+0x22,1)==CHR(0xf3).AND.;
              SUBS(m.q_str2,m.q_p2+0x23,1)==CHR(0xa5).AND.;
              SUBS(m.q_str2,m.q_p2+0x24,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x25,1)==CHR(0xca).AND.;
              SUBS(m.q_str2,m.q_p2+0x26,1)==CHR(0x83).AND.;
              SUBS(m.q_str2,m.q_p2+0x27,1)==CHR(0xe1).AND.;
              SUBS(m.q_str2,m.q_p2+0x28,1)==CHR(0x03).AND.;
              SUBS(m.q_str2,m.q_p2+0x29,1)==CHR(0xf3).AND.;
              SUBS(m.q_str2,m.q_p2+0x2a,1)==CHR(0xa4).AND.;
              SUBS(m.q_str2,m.q_p2+0x2b,1)==CHR(0x5f).AND.;
              SUBS(m.q_str2,m.q_p2+0x2c,1)==CHR(0x5e).AND.;
              SUBS(m.q_str2,m.q_p2+0x2d,1)==CHR(0x43).AND.;
              SUBS(m.q_str2,m.q_p2+0x2e,1)==CHR(0x43).AND.;
              SUBS(m.q_str2,m.q_p2+0x2f,1)==CHR(0x01).AND.;
              SUBS(m.q_str2,m.q_p2+0x30,1)==CHR(0x98).AND.;
              SUBS(m.q_str2,m.q_p2+0x31,1)==CHR(0x7c).AND.;
              SUBS(m.q_str2,m.q_p2+0x32,1)==CHR(0x02).AND.;
              SUBS(m.q_str2,m.q_p2+0x33,1)==CHR(0x00).AND.;
              SUBS(m.q_str2,m.q_p2+0x34,1)==CHR(0x00).AND.;
              SUBS(m.q_str2,m.q_p2+0x35,1)==CHR(0x8b).AND.;
              SUBS(m.q_str2,m.q_p2+0x36,1)==CHR(0xc3))
           m.q_p2_nn=m.q_p2_nn+1
           LOOP
        ENDIF

        EXIT

     ENDDO


     * OldProtect=0x20; // PAGE_EXECUTE_READ
     * VirtualProtect(p1,0x30,0x40,&OldProtect); // PAGE_EXECUTE_READWRITE
     * *(p1+0x00)=0x8D;
     * *(p1+0x01)=0xB8;
     * *(p1+0x02)=0xE8;
     * *(p1+0x03)=0x02;
     * *(p1+0x04)=0x00;
     * *(p1+0x05)=0x00;
     * *(p1+0x06)=0x8B;
     * *(p1+0x07)=0x0F;
     * *(p1+0x08)=0x8B;
     * *(p1+0x09)=0x11;
     * *(p1+0x0A)=0x03;
     * *(p1+0x0B)=0x57;
     * *(p1+0x0C)=0x08;
     * *(p1+0x0D)=0x8B;
     * *(p1+0x0E)=0x74;
     * *(p1+0x0F)=0x24;
     * *(p1+0x10)=0x10;
     * *(p1+0x11)=0x80;
     * *(p1+0x12)=0xFB;
     * *(p1+0x13)=0x53;
     * *(p1+0x14)=0x75;
     * *(p1+0x15)=0x09;
     * *(p1+0x16)=0x8B;
     * *(p1+0x17)=0x4D;
     * *(p1+0x18)=0x00;
     * *(p1+0x19)=0x39;
     * *(p1+0x1A)=0x59;
     * *(p1+0x1B)=0xF0;
     * *(p1+0x1C)=0x75;
     * *(p1+0x1D)=0x01;
     * *(p1+0x1E)=0x43;
     * *(p1+0x1F)=0x8D;
     * *(p1+0x20)=0x4B;
     * *(p1+0x21)=0x02;
     * *(p1+0x22)=0x89;
     * *(p1+0x23)=0x0A;
     * *(p1+0x24)=0x8B;
     * *(p1+0x25)=0xCB;
     * *(p1+0x26)=0x8D;
     * *(p1+0x27)=0x7A;
     * *(p1+0x28)=0x02;
     * VirtualProtect(p1,0x30,OldProtect,&OldProtect);

     * OldProtect=0x20; // PAGE_EXECUTE_READ
     * VirtualProtect(p2,0x30,0x40,&OldProtect); // PAGE_EXECUTE_READWRITE
     * *(p2+0x00)=0x8D;
     * *(p2+0x01)=0xB8;
     * *(p2+0x02)=0x70;
     * *(p2+0x03)=0x02;
     * *(p2+0x04)=0x00;
     * *(p2+0x05)=0x00;
     * *(p2+0x06)=0x8B;
     * *(p2+0x07)=0x0F;
     * *(p2+0x08)=0x8B;
     * *(p2+0x09)=0x11;
     * *(p2+0x0A)=0x03;
     * *(p2+0x0B)=0x57;
     * *(p2+0x0C)=0x0C;
     * *(p2+0x0D)=0x8B;
     * *(p2+0x0E)=0x74;
     * *(p2+0x0F)=0x24;
     * *(p2+0x10)=0x10;
     * *(p2+0x11)=0x80;
     * *(p2+0x12)=0xFB;
     * *(p2+0x13)=0x53;
     * *(p2+0x14)=0x75;
     * *(p2+0x15)=0x09;
     * *(p2+0x16)=0x8B;
     * *(p2+0x17)=0x4D;
     * *(p2+0x18)=0x00;
     * *(p2+0x19)=0x39;
     * *(p2+0x1A)=0x59;
     * *(p2+0x1B)=0xF0;
     * *(p2+0x1C)=0x75;
     * *(p2+0x1D)=0x01;
     * *(p2+0x1E)=0x43;
     * *(p2+0x1F)=0x8D;
     * *(p2+0x20)=0x4B;
     * *(p2+0x21)=0x02;
     * *(p2+0x22)=0x89;
     * *(p2+0x23)=0x0A;
     * *(p2+0x24)=0x8B;
     * *(p2+0x25)=0xCB;
     * *(p2+0x26)=0x8D;
     * *(p2+0x27)=0x7A;
     * *(p2+0x28)=0x02;
     * VirtualProtect(p2,0x30,OldProtect,&OldProtect);

     PRIVATE m.q_str1
     m.q_str1=REPL(CHR(0),0x30)
     =readprocessmemory(getcurrentprocess(),m.q_hmodule0+0x040000+m.q_p1-1+0x00,@m.q_str1,LEN(m.q_str1),0)
     m.q_str1=STUFF(m.q_str1,0x00+1,1,CHR(0x8d))
     m.q_str1=STUFF(m.q_str1,0x01+1,1,CHR(0xb8))
     m.q_str1=STUFF(m.q_str1,0x02+1,1,CHR(0xe8))
     m.q_str1=STUFF(m.q_str1,0x03+1,1,CHR(0x02))
     m.q_str1=STUFF(m.q_str1,0x04+1,1,CHR(0x00))
     m.q_str1=STUFF(m.q_str1,0x05+1,1,CHR(0x00))
     m.q_str1=STUFF(m.q_str1,0x06+1,1,CHR(0x8b))
     m.q_str1=STUFF(m.q_str1,0x07+1,1,CHR(0x0f))
     m.q_str1=STUFF(m.q_str1,0x08+1,1,CHR(0x8b))
     m.q_str1=STUFF(m.q_str1,0x09+1,1,CHR(0x11))
     m.q_str1=STUFF(m.q_str1,0x0a+1,1,CHR(0x03))
     m.q_str1=STUFF(m.q_str1,0x0b+1,1,CHR(0x57))
     m.q_str1=STUFF(m.q_str1,0x0c+1,1,CHR(0x08))
     m.q_str1=STUFF(m.q_str1,0x0d+1,1,CHR(0x8b))
     m.q_str1=STUFF(m.q_str1,0x0e+1,1,CHR(0x74))
     m.q_str1=STUFF(m.q_str1,0x0f+1,1,CHR(0x24))
     m.q_str1=STUFF(m.q_str1,0x10+1,1,CHR(0x10))
     m.q_str1=STUFF(m.q_str1,0x11+1,1,CHR(0x80))
     m.q_str1=STUFF(m.q_str1,0x12+1,1,CHR(0xfb))
     m.q_str1=STUFF(m.q_str1,0x13+1,1,CHR(0x53))
     m.q_str1=STUFF(m.q_str1,0x14+1,1,CHR(0x75))
     m.q_str1=STUFF(m.q_str1,0x15+1,1,CHR(0x09))
     m.q_str1=STUFF(m.q_str1,0x16+1,1,CHR(0x8b))
     m.q_str1=STUFF(m.q_str1,0x17+1,1,CHR(0x4d))
     m.q_str1=STUFF(m.q_str1,0x18+1,1,CHR(0x00))
     m.q_str1=STUFF(m.q_str1,0x19+1,1,CHR(0x39))
     m.q_str1=STUFF(m.q_str1,0x1a+1,1,CHR(0x59))
     m.q_str1=STUFF(m.q_str1,0x1b+1,1,CHR(0xf0))
     m.q_str1=STUFF(m.q_str1,0x1c+1,1,CHR(0x75))
     m.q_str1=STUFF(m.q_str1,0x1d+1,1,CHR(0x01))
     m.q_str1=STUFF(m.q_str1,0x1e+1,1,CHR(0x43))
     m.q_str1=STUFF(m.q_str1,0x1f+1,1,CHR(0x8d))
     m.q_str1=STUFF(m.q_str1,0x20+1,1,CHR(0x4b))
     m.q_str1=STUFF(m.q_str1,0x21+1,1,CHR(0x02))
     m.q_str1=STUFF(m.q_str1,0x22+1,1,CHR(0x89))
     m.q_str1=STUFF(m.q_str1,0x23+1,1,CHR(0x0a))
     m.q_str1=STUFF(m.q_str1,0x24+1,1,CHR(0x8b))
     m.q_str1=STUFF(m.q_str1,0x25+1,1,CHR(0xcb))
     m.q_str1=STUFF(m.q_str1,0x26+1,1,CHR(0x8d))
     m.q_str1=STUFF(m.q_str1,0x27+1,1,CHR(0x7a))
     m.q_str1=STUFF(m.q_str1,0x28+1,1,CHR(0x02))

     PRIVATE m.q_str2
     m.q_str2=REPL(CHR(0),0x30)
     =readprocessmemory(getcurrentprocess(),m.q_hmodule0+0x040000+m.q_p2-1+0x00,@m.q_str2,LEN(m.q_str2),0)
     m.q_str2=STUFF(m.q_str2,0x00+1,1,CHR(0x8d))
     m.q_str2=STUFF(m.q_str2,0x01+1,1,CHR(0xb8))
     m.q_str2=STUFF(m.q_str2,0x02+1,1,CHR(0x70))
     m.q_str2=STUFF(m.q_str2,0x03+1,1,CHR(0x02))
     m.q_str2=STUFF(m.q_str2,0x04+1,1,CHR(0x00))
     m.q_str2=STUFF(m.q_str2,0x05+1,1,CHR(0x00))
     m.q_str2=STUFF(m.q_str2,0x06+1,1,CHR(0x8b))
     m.q_str2=STUFF(m.q_str2,0x07+1,1,CHR(0x0f))
     m.q_str2=STUFF(m.q_str2,0x08+1,1,CHR(0x8b))
     m.q_str2=STUFF(m.q_str2,0x09+1,1,CHR(0x11))
     m.q_str2=STUFF(m.q_str2,0x0a+1,1,CHR(0x03))
     m.q_str2=STUFF(m.q_str2,0x0b+1,1,CHR(0x57))
     m.q_str2=STUFF(m.q_str2,0x0c+1,1,CHR(0x0c))
     m.q_str2=STUFF(m.q_str2,0x0d+1,1,CHR(0x8b))
     m.q_str2=STUFF(m.q_str2,0x0e+1,1,CHR(0x74))
     m.q_str2=STUFF(m.q_str2,0x0f+1,1,CHR(0x24))
     m.q_str2=STUFF(m.q_str2,0x10+1,1,CHR(0x10))
     m.q_str2=STUFF(m.q_str2,0x11+1,1,CHR(0x80))
     m.q_str2=STUFF(m.q_str2,0x12+1,1,CHR(0xfb))
     m.q_str2=STUFF(m.q_str2,0x13+1,1,CHR(0x53))
     m.q_str2=STUFF(m.q_str2,0x14+1,1,CHR(0x75))
     m.q_str2=STUFF(m.q_str2,0x15+1,1,CHR(0x09))
     m.q_str2=STUFF(m.q_str2,0x16+1,1,CHR(0x8b))
     m.q_str2=STUFF(m.q_str2,0x17+1,1,CHR(0x4d))
     m.q_str2=STUFF(m.q_str2,0x18+1,1,CHR(0x00))
     m.q_str2=STUFF(m.q_str2,0x19+1,1,CHR(0x39))
     m.q_str2=STUFF(m.q_str2,0x1a+1,1,CHR(0x59))
     m.q_str2=STUFF(m.q_str2,0x1b+1,1,CHR(0xf0))
     m.q_str2=STUFF(m.q_str2,0x1c+1,1,CHR(0x75))
     m.q_str2=STUFF(m.q_str2,0x1d+1,1,CHR(0x01))
     m.q_str2=STUFF(m.q_str2,0x1e+1,1,CHR(0x43))
     m.q_str2=STUFF(m.q_str2,0x1f+1,1,CHR(0x8d))
     m.q_str2=STUFF(m.q_str2,0x20+1,1,CHR(0x4b))
     m.q_str2=STUFF(m.q_str2,0x21+1,1,CHR(0x02))
     m.q_str2=STUFF(m.q_str2,0x22+1,1,CHR(0x89))
     m.q_str2=STUFF(m.q_str2,0x23+1,1,CHR(0x0a))
     m.q_str2=STUFF(m.q_str2,0x24+1,1,CHR(0x8b))
     m.q_str2=STUFF(m.q_str2,0x25+1,1,CHR(0xcb))
     m.q_str2=STUFF(m.q_str2,0x26+1,1,CHR(0x8d))
     m.q_str2=STUFF(m.q_str2,0x27+1,1,CHR(0x7a))
     m.q_str2=STUFF(m.q_str2,0x28+1,1,CHR(0x02))

     PRIVATE m.q_oldprotect1
     m.q_oldprotect1=0x20 && PAGE_EXECUTE_READ
     =virtualprotect(m.q_hmodule0+0x040000+m.q_p1-1,0x30,0x40,@m.q_oldprotect1) && PAGE_EXECUTE_READWRITE

     PRIVATE m.q_oldprotect2
     m.q_oldprotect2=0x20 && PAGE_EXECUTE_READ
     =virtualprotect(m.q_hmodule0+0x040000+m.q_p2-1,0x30,0x40,@m.q_oldprotect2) && PAGE_EXECUTE_READWRITE

     =writeprocessmemory(getcurrentprocess(),m.q_hmodule0+0x040000+m.q_p1-1+0x00,m.q_str1,LEN(m.q_str1),0)
     =writeprocessmemory(getcurrentprocess(),m.q_hmodule0+0x040000+m.q_p2-1+0x00,m.q_str2,LEN(m.q_str2),0)

     =virtualprotect(m.q_hmodule0+0x040000+m.q_p1-1,0x30,m.q_oldprotect1,@m.q_oldprotect1)
     =virtualprotect(m.q_hmodule0+0x040000+m.q_p2-1,0x30,m.q_oldprotect2,@m.q_oldprotect2)

     m.q_vfp9fixbreakpoint=.T.
     RETU m.q_vfp9fixbreakpoint

     * END OF PROC F_VFP9FIXBREAKPOINT.


     6, Recommend to add the following code to the program file vfpstart.prg:

     * VFP9FixBreakPoint

     #IF ROUND(VAL(CHRTRAN(UPPE(VERSION()),"MICROSOFTVISUALFOXPRO","")),2)=9.0
     =f_vfp9fixbreakpoint()
     #ENDI

     then build the executable file vfpstart.exe from the program file vfpstart.prg:
     BUILD PROJECT vfpstart.pjx FROM vfpstart.prg
     BUILD EXE vfpstart.exe FROM vfpstart.pjx

     then add the following code to the file config.fpw:
     COMMAND=DO vfpstart.exe

     then when we run:
     VFP9.EXE -Cconfig.fpw

     vfp will run DO vfpstart.exe first,
     now it seems there is no invisible breakpoint.


     7, The fix code can fix almost all vfp statements except the structured programming statements such as:

     DO CASE ... ENDCASE
     DO WHILE ... ENDDO
     FOR EACH ... ENDFOR
     FOR ... ENDFOR
     IF ... ENDIF
     SCAN ... ENDSCAN
     TRY ... ENDTRY

     If the structured programming statement has invisible breakpoint,
     we can fix it manually.
     
     For example,
     IF "123456789012345678901234567890123456789012345678901234567890"="12345678"
     we can change it to:
     IF "123456789012345678901234567890123456789012345678901234567890"="12345678" .OR..F. && fix invisible breakpoint

     We can run checkbreakpoint.prg to check the invisible breakpoints.


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.


5. REFERENCE WEBSITES:

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

     2, foxite.com:
     http://www.foxite.com/archives/debugger-stops-without-breakpoints-0000340467.htm
     http://www.foxite.com/archives/debugger-disconnect-0000256551.htm
     http://www.foxite.com/archives/breakpoint-0000227237.htm

     3, foxclub.ru:
     http://forum.foxclub.ru/read.php?29,530804,page=1

     4, dbmonster.com:
     http://www.dbmonster.com/Uwe/Forum.aspx/foxpro-menu/248/Invisible-or-phantom-breakpoints


6. OTHER:

     For reference only, there is no guarantees.

     Any questions or suggestions, please e-mail to ccb2000@163.com.