------------------------------------------------------------
[BUG/PRB.] VFP 9.0 FIX - INVISIBLE BREAKPOINT
January 2026
------------------------------------------------------------
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 compiled 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 compiled 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 compiled 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 compiled p-code is 0x0055, 0x0155, 0x0255, etc.,
then the breakpoint is incorrect.
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
http://www.baiyujia.com/vfpdocuments/f_vfp9fix224.asp
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 send me an email at ccb2000@163.com.
|